DGtal 2.1.1
Loading...
Searching...
No Matches
PolyscopeViewer.ih
1/**
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 **/
15
16/**
17 * @file PolyscopeViewer.ih
18 * @author Bastien Doignies <bastien.doignies@liris.cnrs.fr>
19 *
20 * @date 2025/05/11
21 *
22 * Implementation file for 3D Polyscope Viewer
23 *
24 * This file is part of the DGtal library.
25 */
26
27namespace DGtal {
28 namespace drawutils {
29 glm::vec3 toglm(const DGtal::Color& col) {
30 return glm::vec3{col.r(), col.g(), col.b()};
31 }
32
33 std::vector<glm::vec3> toglm(const std::vector<DGtal::Color>& col) {
34 std::vector<glm::vec3> colors(col.size());
35 for (size_t i = 0; i < colors.size(); ++i) {
36 colors[i] = toglm(col[i]);
37 }
38 return colors;
39 }
40
41 glm::mat4 toglm(const Eigen::Affine3d& transform) {
42 glm::mat4 glmmat(1.f);
43 Eigen::Matrix4d mat = transform.matrix();
44
45 for (int i = 0; i < 4; ++i)
46 for (int j = 0; j < 4; ++j)
47 glmmat[i][j] = static_cast<float>(mat(j, i));
48 return glmmat;
49 }
50 }
51
52 template <typename Space, typename KSpace>
53 void PolyscopeViewer<Space, KSpace>::setCallback(typename Display3D<Space, KSpace>::Callback* callback) {
54 Display3D<Space, KSpace>::setCallback(callback);
55 if (this->myCallback != nullptr) {
56 polyscope::state::userCallback = [this]() { this->polyscopeCallback(); };
57 } else {
58 polyscope::state::userCallback = nullptr; // Remove callback
59 }
60 }
61
62 template <typename Space, typename KSpace>
63 void PolyscopeViewer<Space, KSpace>::renderClippingPlanes() {
64 using namespace drawutils;
65
66 // Draw clipping planes
67 for (const auto& plane : this->planes) {
68 const glm::vec3 normal { plane.a, plane.b, plane.c };
69 glm::vec3 pos {0, 0, 0};
70
71 if (plane.a != 0) { pos.x = -plane.d / plane.a; }
72 else if (plane.b != 0) { pos.y = -plane.d / plane.b; }
73 else if (plane.c != 0) { pos.z = -plane.d / plane.c; }
74 else continue;
75
76 polyscope::SlicePlane* ps = polyscope::addSceneSlicePlane();
77 if (!plane.style.useDefaultColors)
78 ps->setColor(toglm(plane.style.color));
79
80 //TODO: Keep this as default ?
81 ps->setDrawPlane(true);
82 ps->setPose(pos, normal);
83 }
84 }
85
86 template <typename Space, typename KSpace>
87 void PolyscopeViewer<Space, KSpace>::setGeneralProperties(polyscope::Structure* structure, const DisplayData<typename Space::RealPoint>& ddata) {
88 using namespace drawutils;
89
90 structure->setTransform(toglm(ddata.transform));
91 structure->setTransparency(ddata.style.color.a());
92 }
93
94 template <typename Space, typename KSpace>
95 void PolyscopeViewer<Space, KSpace>::registerPointCloud(const std::string& name, const DisplayData<typename Space::RealPoint>& ddata) {
96 using namespace drawutils;
97
98 auto* pCloud = polyscope::registerPointCloud(name, ddata.vertices);
99
100 setGeneralProperties(pCloud, ddata);
101 if (!ddata.style.useDefaultColors) {
102 pCloud->setPointColor(toglm(ddata.style.color));
103 }
104
105 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::VERTEX]) {
106 pCloud->addScalarQuantity(pname, vals)->setEnabled(true);
107 }
108
109 for (const auto& [pname, vals] : ddata.vectorQuantities[QuantityScale::VERTEX]) {
110 auto* q = pCloud->addVectorQuantity(pname, vals);
111 q->setEnabled(true);
112 q->setVectorLengthScale(VectorScale);
113 }
114
115 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::VERTEX]) {
116 pCloud->addColorQuantity(pname, toglm(vals))->setEnabled(true);
117 }
118 pCloud->setPointRadius(ddata.style.width * BallToCubeRatio);
119 }
120
121 template <typename Space, typename KSpace>
122 void PolyscopeViewer<Space, KSpace>::registerLineNetwork(const std::string& name, const DisplayData<typename Space::RealPoint>& ddata) {
123 using namespace drawutils;
124
125 auto* cNetwork = polyscope::registerCurveNetwork(name, ddata.vertices, makeIndices<2>(ddata.vertices.size() / 2));
126
127 setGeneralProperties(cNetwork, ddata);
128 if (!ddata.style.useDefaultColors) {
129 cNetwork->setColor(toglm(ddata.style.color));
130 }
131
132 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::VERTEX]) {
133 cNetwork->addNodeScalarQuantity(pname, vals)->setEnabled(true);
134 }
135 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::EDGE]) {
136 cNetwork->addEdgeScalarQuantity(pname, vals)->setEnabled(true);
137 }
138
139 for (const auto& [pname, vals] : ddata.vectorQuantities[QuantityScale::VERTEX]) {
140 auto* q = cNetwork->addNodeVectorQuantity(pname, vals);
141 q->setVectorLengthScale(VectorScale);
142 q->setEnabled(true);
143 }
144 for (const auto& [pname, vals] : ddata.vectorQuantities[QuantityScale::EDGE]) {
145 auto* q = cNetwork->addEdgeVectorQuantity(pname, vals);
146 q->setVectorLengthScale(VectorScale);
147 q->setEnabled(true);
148 }
149
150 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::VERTEX]) {
151 cNetwork->addEdgeColorQuantity(pname, toglm(vals))->setEnabled(true);
152 }
153 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::EDGE]) {
154 cNetwork->addEdgeColorQuantity(pname, toglm(vals))->setEnabled(true);
155 }
156 }
157
158 template <typename Space, typename KSpace>
159 void PolyscopeViewer<Space, KSpace>::registerSurfaceMesh(const std::string& name, const DisplayData<typename Space::RealPoint>& ddata) {
160 using namespace drawutils;
161
162 polyscope::SurfaceMesh* mesh = nullptr;
163 if (ddata.elementSize == 3) {
164 mesh = polyscope::registerSurfaceMesh(name, ddata.vertices, makeIndices<3>(ddata.vertices.size() / 3));
165 } else if (ddata.elementSize == 4) {
166 mesh = polyscope::registerSurfaceMesh(name, ddata.vertices, makeIndices<4>(ddata.vertices.size() / 4));
167 } else {
168 mesh = polyscope::registerSurfaceMesh(name, ddata.vertices, ddata.indices);
169 }
170
171 setGeneralProperties(mesh, ddata);
172 if (!ddata.style.useDefaultColors) {
173 mesh->setSurfaceColor(toglm(ddata.style.color));
174 }
175
176 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::VERTEX]) {
177 mesh->addVertexScalarQuantity(pname, vals)->setEnabled(true);
178 }
179 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::EDGE]) {
180 mesh->addEdgeScalarQuantity(pname, vals)->setEnabled(true);
181 }
182 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::FACE]) {
183 mesh->addFaceScalarQuantity(pname, vals)->setEnabled(true);
184 }
185
186 for (const auto& [pname, vals] : ddata.vectorQuantities[QuantityScale::VERTEX]) {
187 auto* q = mesh->addVertexVectorQuantity(pname, vals);
188 q->setVectorLengthScale(VectorScale);
189 q->setEnabled(true);
190 }
191 for (const auto& [pname, vals] : ddata.vectorQuantities[QuantityScale::FACE]) {
192 auto* q = mesh->addFaceVectorQuantity(pname, vals);
193 q->setVectorLengthScale(VectorScale);
194 q->setEnabled(true);
195 }
196
197 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::VERTEX]) {
198 mesh->addVertexColorQuantity(pname, toglm(vals))->setEnabled(true);
199 }
200 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::FACE]) {
201 mesh->addFaceColorQuantity(pname, toglm(vals))->setEnabled(true);
202 }
203 }
204
205 template <typename Space, typename KSpace>
206 void PolyscopeViewer<Space, KSpace>::registerSparseVolumeGrid(const std::string& name, const DisplayData<typename Space::RealPoint>& ddata) {
207 using namespace drawutils;
208 const glm::vec3 origin = {0., 0., 0.};
209 const glm::vec3 width = {1., 1., 1.};
210
211 polyscope::SparseVolumeGrid* grid = polyscope::registerSparseVolumeGrid(name, origin, width, ddata.vertices);
212
213 setGeneralProperties(grid, ddata);
214 if (!ddata.style.useDefaultColors) {
215 grid->setColor(toglm(ddata.style.color));
216 }
217
218 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::CELL]) {
219 grid->addCellScalarQuantity(pname, vals)->setEnabled(true);
220 }
221
222 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::CELL]) {
223 grid->addCellColorQuantity(pname, toglm(vals))->setEnabled(true);
224 }
225 }
226
227 template <typename Space, typename KSpace>
228 void PolyscopeViewer<Space, KSpace>::registerVolumeMesh(const std::string& name, const DisplayData<typename Space::RealPoint>& ddata) {
229 using namespace drawutils;
230
231 polyscope::VolumeMesh* mesh = polyscope::registerVolumeMesh(name, ddata.vertices, makeIndices<8>(ddata.vertices.size() / 8));
232
233 setGeneralProperties(mesh, ddata);
234 if (!ddata.style.useDefaultColors) {
235 mesh->setColor(toglm(ddata.style.color));
236 }
237
238 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::VERTEX]) {
239 mesh->addVertexScalarQuantity(pname, vals)->setEnabled(true);
240 }
241 for (const auto& [pname, vals] : ddata.scalarQuantities[QuantityScale::CELL]) {
242 mesh->addCellScalarQuantity(pname, vals)->setEnabled(true);
243 }
244
245 for (const auto& [pname, vals] : ddata.vectorQuantities[QuantityScale::VERTEX]) {
246 auto* q = mesh->addVertexVectorQuantity(pname, vals);
247 q->setVectorLengthScale(VectorScale);
248 q->setEnabled(true);
249 }
250 for (const auto& [pname, vals] : ddata.vectorQuantities[QuantityScale::CELL]) {
251 auto* q = mesh->addCellVectorQuantity(pname, vals);
252 q->setVectorLengthScale(VectorScale);
253 q->setEnabled(true);
254 }
255
256 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::VERTEX]) {
257 mesh->addVertexColorQuantity(pname, toglm(vals))->setEnabled(true);
258 }
259 for (const auto& [pname, vals] : ddata.colorQuantities[QuantityScale::CELL]) {
260 mesh->addCellColorQuantity(pname, toglm(vals))->setEnabled(true);
261 }
262 }
263
264 template <typename Space, typename KSpace>
265 void PolyscopeViewer<Space, KSpace>::renderNewData() {
266 using namespace drawutils;
267
268 for (const std::string& name : this->myToRender) {
269 auto it = this->data.find(name);
270 if (it == this->data.end()) continue;
271
272 const auto& ddata = it->second;
273 const auto& vertices = ddata.vertices;
274
275 if (vertices.size() == 0) continue;
276
277 switch(ddata.elementSize) {
278 case 1: {
279 if (ddata.style.mode & DisplayStyle::BALLS) registerPointCloud(name, ddata);
280 else registerSparseVolumeGrid(name, ddata);
281
282 break;
283 }
284 case 2: registerLineNetwork(name, ddata); break;
285 case 0:
286 case 3:
287 case 4: registerSurfaceMesh(name, ddata); break;
288 case 8: registerVolumeMesh(name, ddata); break;
289 default:
290 break;
291 };
292 }
293 }
294
295
296 template <typename Space, typename KSpace>
297 void PolyscopeViewer<Space, KSpace>::polyscopeCallback() {
298 this->myCallback->OnUI(nullptr);
299
300 ImGuiIO& io = ImGui::GetIO();
301 if (io.MouseClicked[0])
302 {
303 glm::vec2 screenCoords{io.MousePos.x, io.MousePos.y};
304 auto [structure, index] =
305 polyscope::pick::pickAtScreenCoords(screenCoords);
306
307 if (structure != nullptr) {
308 void* viewerData = structure;
309 std::string name = structure->getName();
310
311 auto& ddata = this->data[name];
312 this->myCallback->OnClick(name, index, ddata, viewerData);
313 }
314 }
315 }
316}