ArVizInteractExample.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::ArmarXObjects::ArVizInteractExample
17 * @author Fabian Paus ( fabian dot paus at kit dot edu )
18 * @date 2019
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
27
29
30namespace armarx
31{
32
34 {
35 SingleSlider(std::string const& name, viz::Color color) : box(name), color(color)
36 {
37 }
38
41
42 Eigen::Vector3f initial = Eigen::Vector3f::Zero();
43 Eigen::Vector3f translation = Eigen::Vector3f::Zero();
44 };
45
47 {
48 SlidersState(Eigen::Vector3f origin) :
50 x("BoxX", viz::Color::red()),
51 y("BoxY", viz::Color::green()),
52 z("BoxZ", viz::Color::blue()),
53 sphere("Sphere")
54 {
55 float boxSize = 50.0f;
56
57 x.initial = origin + Eigen::Vector3f(0.5f * ARROW_LENGTH, 0.0f, 0.0f);
58 x.box.position(x.initial).color(x.color).size(boxSize).enable(
59 viz::interaction().translation(viz::AXES_X).hideDuringTransform());
60
61 y.initial = origin + Eigen::Vector3f(0.0f, 0.5f * ARROW_LENGTH, 0.0f);
62 y.box.position(y.initial).color(y.color).size(boxSize).enable(
63 viz::interaction().translation(viz::AXES_Y).hideDuringTransform());
64
65 z.initial = origin + Eigen::Vector3f(0.0f, 0.0f, 0.5f * ARROW_LENGTH);
66 z.box.position(z.initial).color(z.color).size(boxSize).enable(
67 viz::interaction().translation(viz::AXES_Z).hideDuringTransform());
68
69 sphere.position(origin + 0.5f * ARROW_LENGTH * Eigen::Vector3f(1.0f, 1.0f, 1.0f))
70 .color(viz::Color::orange())
71 .radius(30.0f);
72 }
73
74 static constexpr const float ARROW_LENGTH = 1000.0f;
75
76 void
78 {
79 layerInteract = arviz.layer("Sliders");
80
81 float arrowWidth = 10.0f;
82
83 viz::Arrow arrowX =
84 viz::Arrow("ArrowX")
85 .color(viz::Color::red())
86 .fromTo(origin, origin + Eigen::Vector3f(ARROW_LENGTH, 0.0f, 0.0f))
87 .width(arrowWidth);
88 layerInteract.add(arrowX);
89
90 viz::Arrow arrowY =
91 viz::Arrow("ArrowY")
92 .color(viz::Color::green())
93 .fromTo(origin, origin + Eigen::Vector3f(0.0f, ARROW_LENGTH, 0.0f))
94 .width(arrowWidth);
95 layerInteract.add(arrowY);
96
97 viz::Arrow arrowZ =
98 viz::Arrow("ArrowZ")
99 .color(viz::Color::blue())
100 .fromTo(origin, origin + Eigen::Vector3f(0.0f, 0.0f, ARROW_LENGTH))
101 .width(arrowWidth);
102 layerInteract.add(arrowZ);
103
104
105 layerInteract.add(x.box);
106 layerInteract.add(y.box);
107 layerInteract.add(z.box);
108
109 layerResult = arviz.layer("SlidersResult");
110 layerResult.add(sphere);
111 }
112
113 void
115 {
116 std::string const& element = interaction.element();
117 Eigen::Matrix4f transform = interaction.transformation();
118 Eigen::Vector3f translation = transform.block<3, 1>(0, 3);
119
120 SingleSlider* slider = nullptr;
121 if (element == "BoxX")
122 {
123 slider = &x;
124 }
125 else if (element == "BoxY")
126 {
127 slider = &y;
128 }
129 else if (element == "BoxZ")
130 {
131 slider = &z;
132 }
133 else
134 {
135 ARMARX_WARNING << "Unknown interaction: " << element;
136 return;
137 }
138
139 switch (interaction.type())
140 {
142 {
143 slider->translation = translation;
144
145 Eigen::Vector3f spherePosition(x.initial.x() + x.translation.x(),
146 y.initial.y() + y.translation.y(),
147 z.initial.z() + z.translation.z());
148 sphere.position(spherePosition);
149
150 stage->add(layerResult);
151 }
152 break;
153
155 {
156 // Do nothing
157 }
158 break;
159
161 {
162 // If an object is deselected, we apply the transformation
163 slider->initial = slider->initial + slider->translation;
164 slider->translation = Eigen::Vector3f::Zero();
165 ARMARX_IMPORTANT << "Setting position to " << slider->initial.transpose();
166 slider->box.position(slider->initial);
167
168 stage->add(layerInteract);
169 }
170 break;
171
172 default:
173 {
174 // Do nothing for the other interaction types
175 }
176 break;
177 }
178 }
179
180 Eigen::Vector3f origin;
184
186
189 };
190
191 // ---------------
192
193 // What abstractions are needed?
194 // MovableElement
195 // SpawnerElement
196
197
199 {
200 SlidersState2(Eigen::Vector3f origin) :
201 origin(origin), x("BoxX"), y("BoxY"), z("BoxZ"), sphere("Sphere")
202 {
203 float boxSize = 50.0f;
204
205 // We use the Transformable<T>::position to set the position
206 // This keeps track of the internal state
207 x.position(origin + Eigen::Vector3f(0.5f * ARROW_LENGTH, 0.0f, 0.0f));
208 // A movable object is always hidden during the transformation
209 // The hideDuringTransform() flag is automatically set here
210 x.enable(viz::interaction().translation(viz::AXES_X));
211
212 // Other attributes of the element can be set directly on the member
213 x.element.color(viz::Color::red()).size(boxSize);
214
215 y.position(origin + Eigen::Vector3f(0.0f, 0.5f * ARROW_LENGTH, 0.0f));
216 y.enable(viz::interaction().translation(viz::AXES_Y));
217
218 y.element.color(viz::Color::green()).size(boxSize);
219
220 z.position(origin + Eigen::Vector3f(0.0f, 0.0f, 0.5f * ARROW_LENGTH));
221 z.enable(viz::interaction().translation(viz::AXES_Z));
222 z.element.color(viz::Color::blue()).size(boxSize);
223
224 sphere.position(origin + 0.5f * ARROW_LENGTH * Eigen::Vector3f(1.0f, 1.0f, 1.0f))
225 .color(viz::Color::orange())
226 .radius(30.0f);
227 }
228
229 static constexpr const float ARROW_LENGTH = 1000.0f;
230
231 void
233 {
234 layerInteract = arviz.layer("Sliders2");
235
236 float arrowWidth = 10.0f;
237
238 viz::Arrow arrowX =
239 viz::Arrow("ArrowX")
240 .color(viz::Color::red())
241 .fromTo(origin, origin + Eigen::Vector3f(ARROW_LENGTH, 0.0f, 0.0f))
242 .width(arrowWidth);
243 layerInteract.add(arrowX);
244
245 viz::Arrow arrowY =
246 viz::Arrow("ArrowY")
247 .color(viz::Color::green())
248 .fromTo(origin, origin + Eigen::Vector3f(0.0f, ARROW_LENGTH, 0.0f))
249 .width(arrowWidth);
250 layerInteract.add(arrowY);
251
252 viz::Arrow arrowZ =
253 viz::Arrow("ArrowZ")
254 .color(viz::Color::blue())
255 .fromTo(origin, origin + Eigen::Vector3f(0.0f, 0.0f, ARROW_LENGTH))
256 .width(arrowWidth);
257 layerInteract.add(arrowZ);
258
259
260 layerInteract.add(x.element);
261 layerInteract.add(y.element);
262 layerInteract.add(z.element);
263
264 layerResult = arviz.layer("SlidersResult2");
265 layerResult.add(sphere);
266 }
267
268 void
270 {
271 // Let the Transformable<T> handle all events internally
272 bool needsLayerUpdate = false;
273 viz::TransformationResult xResult = x.handle(interaction);
274 needsLayerUpdate |= xResult.needsLayerUpdate;
275 needsLayerUpdate |= y.handle(interaction).needsLayerUpdate;
276 needsLayerUpdate |= z.handle(interaction).needsLayerUpdate;
277 if (needsLayerUpdate)
278 {
279 // At least one Transformable<T> indicated that the layer needs to be updated
280 stage->add(layerInteract);
281 }
282
283 // We could react to specific events
284 if (xResult.wasTransformed)
285 {
286 ARMARX_INFO << "The x slider was transformed: " << x.getCurrentPose().col(3).x();
287 }
288
289 // We handle the transform event ourselves to add custom behavior
290 // Here, we move the sphere based on the position of the sliders
291 if (interaction.type() == viz::InteractionFeedbackType::Transform)
292 {
293 // We can query getCurrentPose() to determine the poses of the sliders
294 // with the transformation applied to them
295 Eigen::Vector3f spherePosition(x.getCurrentPose().col(3).x(),
296 y.getCurrentPose().col(3).y(),
297 z.getCurrentPose().col(3).z());
298 sphere.position(spherePosition);
299
300 stage->add(layerResult);
301 }
302 }
303
304 Eigen::Vector3f origin;
308
310
313 };
314 // ---------------
315
316
317 enum class SpawnerType
318 {
322 };
323
324 enum class SpawnerOption
325 {
328 };
329
330 struct Spawner
331 {
333
334 Eigen::Vector3f position = Eigen::Vector3f::Zero();
335 float size = 100.0f;
336 viz::Color color = viz::Color::black();
337
338 void
339 visualize(int i, viz::Layer& layer)
340 {
341 viz::InteractionDescription interaction =
343 {"Delete All", "Delete All of Type"});
344 std::string name = "Spawner_" + std::to_string(i);
345 switch (type)
346 {
347 case SpawnerType::Box:
348 {
350 interaction);
351 layer.add(box);
352 }
353 break;
355 {
356 viz::Cylinder cylinder = viz::Cylinder(name)
358 .radius(size * 0.5f)
359 .height(size)
360 .color(color)
361 .enable(interaction);
362 layer.add(cylinder);
363 }
364 break;
366 {
367 viz::Sphere sphere = viz::Sphere(name)
369 .radius(size * 0.5f)
370 .color(color)
371 .enable(interaction);
372 layer.add(sphere);
373 }
374 break;
375 }
376 }
377 };
378
380 {
381 int index = 0;
382 Spawner* source = nullptr;
383 Eigen::Matrix4f transform = Eigen::Matrix4f::Identity();
384 Eigen::Vector3f scale = Eigen::Vector3f::Ones();
385
386 void
388 {
389 if (source == nullptr)
390 {
391 ARMARX_WARNING << "Tried to visualize a spawned object that does not have a source";
392 return;
393 }
394
395 viz::InteractionDescription interaction =
396 viz::interaction().selection().contextMenu({"Delete"});
397 std::string name = "Object_" + std::to_string(index);
398
399 Eigen::Matrix4f initial = Eigen::Matrix4f::Identity();
400 initial.block<3, 1>(0, 3) = source->position;
401 Eigen::Matrix4f pose = transform * initial;
402
403 switch (source->type)
404 {
405 case SpawnerType::Box:
406 {
407 viz::Box box = viz::Box(name)
408 .pose(pose)
409 .scale(scale)
410 .size(source->size)
411 .color(source->color)
412 .enable(interaction);
413 layer.add(box);
414 }
415 break;
417 {
418 viz::Cylinder cylinder = viz::Cylinder(name)
419 .pose(pose)
420 .scale(scale)
421 .radius(source->size * 0.5f)
422 .height(source->size)
423 .color(source->color)
424 .enable(interaction);
425 layer.add(cylinder);
426 }
427 break;
429 {
430 viz::Sphere sphere = viz::Sphere(name)
431 .pose(pose)
432 .scale(scale)
433 .radius(source->size * 0.5f)
434 .color(source->color)
435 .enable(interaction);
436 layer.add(sphere);
437 }
438 break;
439 }
440 }
441 };
442
444 {
445 SpawnersState(Eigen::Vector3f origin) : origin(origin)
446 {
447 float size = 100.0f;
448 {
449 Spawner& spawner = spawners.emplace_back();
450 spawner.type = SpawnerType::Box;
451 spawner.position = origin + Eigen::Vector3f(750.0f, 500.0f, 0.5f * size);
452 spawner.color = viz::Color::cyan();
453 }
454 {
455 Spawner& spawner = spawners.emplace_back();
456 spawner.type = SpawnerType::Cylinder;
457 spawner.position = origin + Eigen::Vector3f(1250.0f, 500.0f, 0.5f * size);
458 spawner.color = viz::Color::magenta();
459 }
460 {
461 Spawner& spawner = spawners.emplace_back();
462 spawner.type = SpawnerType::Sphere;
463 spawner.position = origin + Eigen::Vector3f(1000.0f, 750.0f, 0.5f * size);
464 spawner.color = viz::Color::yellow();
465 }
466 }
467
468 void
470 {
471 layerSpawners = arviz.layer("Spawners");
472
473 int index = 0;
474 for (Spawner& spawner : spawners)
475 {
476 spawner.visualize(index, layerSpawners);
477 index += 1;
478 }
479
480 layerObjects = arviz.layer("SpawnedObjects");
481 }
482
483 void
485 {
486 layerObjects.clear();
487 for (auto& object : objects)
488 {
489 object.visualize(layerObjects);
490 }
491 stage->add(layerObjects);
492 }
493
494 void
496 {
497 Spawner* spawner = nullptr;
498 for (int i = 0; i < (int)spawners.size(); ++i)
499 {
500 std::string name = "Spawner_" + std::to_string(i);
501 if (interaction.element() == name)
502 {
503 spawner = &spawners[i];
504 break;
505 }
506 }
507 if (spawner == nullptr)
508 {
509 ARMARX_INFO << "No spawner" << interaction.element();
510 // A spawned object was selected instead of a spawner
511 if (interaction.type() == viz::InteractionFeedbackType::ContextMenuChosen &&
512 interaction.chosenContextMenuEntry() == 0)
513 {
514 // The delete context menu option was chosen
515 // So we remove the object from the internal list and redraw
516 auto newEnd = std::remove_if(objects.begin(),
517 objects.end(),
518 [&interaction](SpawnedObject const& object)
519 {
520 std::string name =
521 "Object_" + std::to_string(object.index);
522 return interaction.element() == name;
523 });
524 objects.erase(newEnd, objects.end());
525
527 }
528 return;
529 }
530
531 switch (interaction.type())
532 {
534 {
535 // Create a spawned object
537 spawnedObject.source = spawner;
538 spawnedObject.transform = Eigen::Matrix4f::Identity();
539 spawnedObject.scale.setOnes();
540 }
541 break;
542
544 {
545 // Update state of spawned object
546 spawnedObject.transform = interaction.transformation();
547 spawnedObject.scale = interaction.scale();
548 if (interaction.isTransformBegin())
549 {
550 // Visualize all other objects except the currently spawned one
552 }
553 if (interaction.isTransformEnd())
554 {
555 spawnedObject.visualize(layerObjects);
556 stage->add(layerObjects);
557 }
558 }
559 break;
560
562 {
563 // Save state of spawned object
564 objects.push_back(spawnedObject);
565 }
566 break;
567
569 {
570 SpawnerOption option = (SpawnerOption)(interaction.chosenContextMenuEntry());
571 switch (option)
572 {
574 {
575 objects.clear();
576 layerObjects.clear();
577
578 stage->add(layerObjects);
579 }
580 break;
582 {
583 auto newEnd = std::remove_if(objects.begin(),
584 objects.end(),
585 [spawner](SpawnedObject const& obj)
586 { return obj.source == spawner; });
587 objects.erase(newEnd, objects.end());
588
590 }
591 break;
592 }
593 }
594
595 default:
596 {
597 // Ignore other interaction types
598 }
599 break;
600 }
601 }
602
603 Eigen::Vector3f origin;
604
605 std::vector<Spawner> spawners;
608 std::vector<SpawnedObject> objects;
609
612 };
613
614 /**
615 * @defgroup Component-ArVizInteractExample ArVizInteractExample
616 * @ingroup RobotAPI-Components
617 *
618 * An example for how to visualize 3D elements via the 3D visualization
619 * framework ArViz.
620 *
621 * The example creates several layers, fills them with visualization
622 * elements, and commits them to ArViz.
623 *
624 * To see the result:
625 * \li Start the component `ArVizStorage`
626 * \li Open the gui plugin `ArViz`
627 * \li Start the component `ArVizInteractExample`
628 *
629 * The scenario `ArVizInteractExample` starts the necessary components,
630 * including the example component.
631 *
632 *
633 * A component which wants to visualize data via ArViz should:
634 * \li `#include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>`
635 * \li Inherit from the `armarx::ArVizComponentPluginUser`. This adds the
636 * necessary properties (e.g. the topic name) and provides a
637 * ready-to-use ArViz client called `arviz`.
638 * \li Use the inherited ArViz client variable `arviz` of type `viz::Client`
639 * to create layers, add visualization elements to the layers,
640 * and commit the layers to the ArViz topic.
641 *
642 * \see ArVizInteractExample
643 *
644 *
645 * @class ArVizInteractExample
646 * @ingroup Component-ArVizInteractExample
647 *
648 * @brief An example for how to use ArViz.
649 *
650 * @see @ref Component-ArVizInteractExample
651 */
653 virtual armarx::Component,
654 // Deriving from armarx::ArVizComponentPluginUser adds necessary properties
655 // and provides a ready-to-use ArViz client called `arviz`.
657 {
658 std::string
659 getDefaultName() const override
660 {
661 return "ArVizInteractExample";
662 }
663
671
672 void
674 {
675 }
676
677 void
679 {
681 task->start();
682 }
683
684 void
686 {
687 const bool join = true;
688 task->stop(join);
689 task = nullptr;
690 }
691
692 void
694 {
695 }
696
697 void
699 {
700 viz::StagedCommit stage;
701
702 viz::Layer regions = arviz.layer("Regions");
703 Eigen::Vector3f origin1(-2000.0f, 0.0f, 0.0f);
704 Eigen::Vector3f origin2(0.0f, 0.0f, 0.0f);
705 Eigen::Vector3f origin3(-2000.0f, -2000.0f, 0.0f);
706 Eigen::Vector3f origin4(0.0f, -2000.0f, 0.0f);
707 {
708 viz::Cylinder separatorX =
709 viz::Cylinder("SeparatorX")
710 .fromTo(origin1, origin1 + 4000.0f * Eigen::Vector3f::UnitX())
711 .radius(5.0f);
712 regions.add(separatorX);
713
714 viz::Cylinder separatorY =
715 viz::Cylinder("SeparatorY")
716 .fromTo(origin4, origin4 + 4000.0f * Eigen::Vector3f::UnitY())
717 .radius(5.0f);
718 regions.add(separatorY);
719
720 stage.add(regions);
721 }
722
723
724 SlidersState sliders(origin1 + Eigen::Vector3f(500.0f, 500.0f, 0.0f));
725 SlidersState2 sliders2(origin3 + Eigen::Vector3f(500.0f, 500.0f, 0.0f));
726 SpawnersState spawners(origin2);
727
728 sliders.visualize(arviz);
729 stage.add(sliders.layerInteract);
730 stage.add(sliders.layerResult);
731
732 sliders2.visualize(arviz);
733 stage.add(sliders2.layerInteract);
734 stage.add(sliders2.layerResult);
735
736 spawners.visualize(arviz);
737 stage.add(spawners.layerSpawners);
738 stage.add(spawners.layerObjects);
739
740 viz::CommitResult result = arviz.commit(stage);
741 ARMARX_INFO << "Initial commit at revision: " << result.revision();
742
743 CycleUtil c(10.0f);
744 while (!task->isStopped())
745 {
746 result = arviz.commit(stage);
747
748 // Reset the stage, so that it can be rebuild during the interaction handling
749 stage.reset();
750
751 stage.requestInteraction(sliders.layerInteract);
752 stage.requestInteraction(sliders2.layerInteract);
753 stage.requestInteraction(spawners.layerSpawners);
754 stage.requestInteraction(spawners.layerObjects);
755
756 viz::InteractionFeedbackRange interactions = result.interactions();
757 for (viz::InteractionFeedback const& interaction : interactions)
758 {
759 if (interaction.layer() == "Sliders")
760 {
761 sliders.handle(interaction, &stage);
762 }
763 if (interaction.layer() == "Sliders2")
764 {
765 sliders2.handle(interaction, &stage);
766 }
767 if (interaction.layer() == "Spawners" ||
768 interaction.layer() == "SpawnedObjects")
769 {
770 spawners.handle(interaction, &stage);
771 }
772 }
773
774 c.waitForCycleDuration();
775 }
776 }
777
779 };
780
782} // namespace armarx
783// The executable's main() is generated automatically by armarx_add_component (decoupled main);
784// the component is wired in via the ARMARX_DECOUPLED_REGISTER_COMPONENT macro above.
#define ARMARX_DECOUPLED_REGISTER_COMPONENT(ComponentT)
Definition Decoupled.h:34
uint8_t index
#define option(type, fn)
constexpr T c
Provides a ready-to-use ArViz client arviz as member variable.
Default component property definition container.
Definition Component.h:70
Baseclass for all ArmarX ManagedIceObjects requiring properties.
Definition Component.h:94
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
This util class helps with keeping a cycle time during a control cycle.
Definition CycleUtil.h:41
IceUtil::Handle< RunningTask< T > > pointer_type
Shared pointer type for convenience.
virtual Layer layer(std::string const &name) const
Definition Client.cpp:80
DerivedT & enable(InteractionDescription const &interactionDescription)
Definition ElementOps.h:309
DerivedT & pose(Eigen::Matrix4f const &pose)
Definition ElementOps.h:176
DerivedT & color(Color color)
Definition ElementOps.h:218
DerivedT & position(float x, float y, float z)
Definition ElementOps.h:136
DerivedT & scale(Eigen::Vector3f scale)
Definition ElementOps.h:254
uint32_t Color
RGBA color.
Definition color.h:8
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
This file is part of ArmarX.
InteractionDescription interaction()
Definition ElementOps.h:109
@ Transform
The element was transformed (translated or rotated).
Definition Interaction.h:24
@ ContextMenuChosen
A context menu entry was chosen.
Definition Interaction.h:21
@ Deselect
An element was deselected.
Definition Interaction.h:18
@ Select
An element was selected.
Definition Interaction.h:16
This file offers overloads of toIce() and fromIce() functions for STL container types.
QColor green()
Definition StyleSheets.h:72
QColor red()
Definition StyleSheets.h:78
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition algorithm.h:351
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
An example for how to use ArViz.
void onInitComponent() override
Pure virtual hook for the subclass.
void onDisconnectComponent() override
Hook for subclass.
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Creates the property definition container.
void onConnectComponent() override
Pure virtual hook for the subclass.
RunningTask< ArVizInteractExample >::pointer_type task
void onExitComponent() override
Hook for subclass.
std::string getDefaultName() const override
Retrieve default name of component.
SingleSlider(std::string const &name, viz::Color color)
SlidersState2(Eigen::Vector3f origin)
void handle(viz::InteractionFeedback const &interaction, viz::StagedCommit *stage)
static constexpr const float ARROW_LENGTH
viz::Transformable< viz::Box > z
void visualize(viz::Client &arviz)
viz::Transformable< viz::Box > y
void handle(viz::InteractionFeedback const &interaction, viz::StagedCommit *stage)
static constexpr const float ARROW_LENGTH
SlidersState(Eigen::Vector3f origin)
void visualize(viz::Client &arviz)
void visualize(viz::Layer &layer)
void visualize(int i, viz::Layer &layer)
void handle(viz::InteractionFeedback const &interaction, viz::StagedCommit *stage)
void visualizeSpawnedObjects(viz::StagedCommit *stage)
std::vector< Spawner > spawners
std::vector< SpawnedObject > objects
void visualize(viz::Client &arviz)
SpawnersState(Eigen::Vector3f origin)
Arrow & fromTo(const Eigen::Vector3f &from, const Eigen::Vector3f &to)
Definition Elements.h:219
Arrow & width(float w)
Definition Elements.h:211
Box & size(Eigen::Vector3f const &s)
Definition Elements.h:52
long revision() const
Definition Client.h:79
InteractionFeedbackRange interactions() const
Definition Client.h:85
Cylinder & height(float h)
Definition Elements.h:84
Cylinder & radius(float r)
Definition Elements.h:76
Cylinder & fromTo(Eigen::Vector3f from, Eigen::Vector3f to)
Definition Elements.cpp:93
Self & contextMenu(std::vector< std::string > const &options)
Definition ElementOps.h:54
Self & scaling(AxesFlags const &axes=AXES_XYZ)
Definition ElementOps.h:83
void add(ElementT const &element)
Definition Layer.h:31
Sphere & radius(float r)
Definition Elements.h:138
A staged commit prepares multiple layers to be committed.
Definition Client.h:30
void requestInteraction(Layer const &layer)
Request interaction feedback for a particular layer.
Definition Client.h:56
void add(Layer const &layer)
Stage a layer to be committed later via client.apply(*this)
Definition Client.h:36
void reset()
Reset all staged layers and interaction requests.
Definition Client.h:66