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
28
30
31namespace armarx
32{
33
35 {
36 SingleSlider(std::string const& name, viz::Color color) : box(name), color(color)
37 {
38 }
39
42
43 Eigen::Vector3f initial = Eigen::Vector3f::Zero();
44 Eigen::Vector3f translation = Eigen::Vector3f::Zero();
45 };
46
48 {
49 SlidersState(Eigen::Vector3f origin) :
51 x("BoxX", viz::Color::red()),
52 y("BoxY", viz::Color::green()),
53 z("BoxZ", viz::Color::blue()),
54 sphere("Sphere")
55 {
56 float boxSize = 50.0f;
57
58 x.initial = origin + Eigen::Vector3f(0.5f * ARROW_LENGTH, 0.0f, 0.0f);
59 x.box.position(x.initial).color(x.color).size(boxSize).enable(
60 viz::interaction().translation(viz::AXES_X).hideDuringTransform());
61
62 y.initial = origin + Eigen::Vector3f(0.0f, 0.5f * ARROW_LENGTH, 0.0f);
63 y.box.position(y.initial).color(y.color).size(boxSize).enable(
64 viz::interaction().translation(viz::AXES_Y).hideDuringTransform());
65
66 z.initial = origin + Eigen::Vector3f(0.0f, 0.0f, 0.5f * ARROW_LENGTH);
67 z.box.position(z.initial).color(z.color).size(boxSize).enable(
68 viz::interaction().translation(viz::AXES_Z).hideDuringTransform());
69
70 sphere.position(origin + 0.5f * ARROW_LENGTH * Eigen::Vector3f(1.0f, 1.0f, 1.0f))
71 .color(viz::Color::orange())
72 .radius(30.0f);
73 }
74
75 static constexpr const float ARROW_LENGTH = 1000.0f;
76
77 void
79 {
80 layerInteract = arviz.layer("Sliders");
81
82 float arrowWidth = 10.0f;
83
84 viz::Arrow arrowX =
85 viz::Arrow("ArrowX")
86 .color(viz::Color::red())
87 .fromTo(origin, origin + Eigen::Vector3f(ARROW_LENGTH, 0.0f, 0.0f))
88 .width(arrowWidth);
89 layerInteract.add(arrowX);
90
91 viz::Arrow arrowY =
92 viz::Arrow("ArrowY")
93 .color(viz::Color::green())
94 .fromTo(origin, origin + Eigen::Vector3f(0.0f, ARROW_LENGTH, 0.0f))
95 .width(arrowWidth);
96 layerInteract.add(arrowY);
97
98 viz::Arrow arrowZ =
99 viz::Arrow("ArrowZ")
100 .color(viz::Color::blue())
101 .fromTo(origin, origin + Eigen::Vector3f(0.0f, 0.0f, ARROW_LENGTH))
102 .width(arrowWidth);
103 layerInteract.add(arrowZ);
104
105
106 layerInteract.add(x.box);
107 layerInteract.add(y.box);
108 layerInteract.add(z.box);
109
110 layerResult = arviz.layer("SlidersResult");
111 layerResult.add(sphere);
112 }
113
114 void
116 {
117 std::string const& element = interaction.element();
118 Eigen::Matrix4f transform = interaction.transformation();
119 Eigen::Vector3f translation = transform.block<3, 1>(0, 3);
120
121 SingleSlider* slider = nullptr;
122 if (element == "BoxX")
123 {
124 slider = &x;
125 }
126 else if (element == "BoxY")
127 {
128 slider = &y;
129 }
130 else if (element == "BoxZ")
131 {
132 slider = &z;
133 }
134 else
135 {
136 ARMARX_WARNING << "Unknown interaction: " << element;
137 return;
138 }
139
140 switch (interaction.type())
141 {
143 {
144 slider->translation = translation;
145
146 Eigen::Vector3f spherePosition(x.initial.x() + x.translation.x(),
147 y.initial.y() + y.translation.y(),
148 z.initial.z() + z.translation.z());
149 sphere.position(spherePosition);
150
151 stage->add(layerResult);
152 }
153 break;
154
156 {
157 // Do nothing
158 }
159 break;
160
162 {
163 // If an object is deselected, we apply the transformation
164 slider->initial = slider->initial + slider->translation;
165 slider->translation = Eigen::Vector3f::Zero();
166 ARMARX_IMPORTANT << "Setting position to " << slider->initial.transpose();
167 slider->box.position(slider->initial);
168
169 stage->add(layerInteract);
170 }
171 break;
172
173 default:
174 {
175 // Do nothing for the other interaction types
176 }
177 break;
178 }
179 }
180
181 Eigen::Vector3f origin;
185
187
190 };
191
192 // ---------------
193
194 // What abstractions are needed?
195 // MovableElement
196 // SpawnerElement
197
198
200 {
201 SlidersState2(Eigen::Vector3f origin) :
202 origin(origin), x("BoxX"), y("BoxY"), z("BoxZ"), sphere("Sphere")
203 {
204 float boxSize = 50.0f;
205
206 // We use the Transformable<T>::position to set the position
207 // This keeps track of the internal state
208 x.position(origin + Eigen::Vector3f(0.5f * ARROW_LENGTH, 0.0f, 0.0f));
209 // A movable object is always hidden during the transformation
210 // The hideDuringTransform() flag is automatically set here
211 x.enable(viz::interaction().translation(viz::AXES_X));
212
213 // Other attributes of the element can be set directly on the member
214 x.element.color(viz::Color::red()).size(boxSize);
215
216 y.position(origin + Eigen::Vector3f(0.0f, 0.5f * ARROW_LENGTH, 0.0f));
217 y.enable(viz::interaction().translation(viz::AXES_Y));
218
219 y.element.color(viz::Color::green()).size(boxSize);
220
221 z.position(origin + Eigen::Vector3f(0.0f, 0.0f, 0.5f * ARROW_LENGTH));
222 z.enable(viz::interaction().translation(viz::AXES_Z));
223 z.element.color(viz::Color::blue()).size(boxSize);
224
225 sphere.position(origin + 0.5f * ARROW_LENGTH * Eigen::Vector3f(1.0f, 1.0f, 1.0f))
226 .color(viz::Color::orange())
227 .radius(30.0f);
228 }
229
230 static constexpr const float ARROW_LENGTH = 1000.0f;
231
232 void
234 {
235 layerInteract = arviz.layer("Sliders2");
236
237 float arrowWidth = 10.0f;
238
239 viz::Arrow arrowX =
240 viz::Arrow("ArrowX")
241 .color(viz::Color::red())
242 .fromTo(origin, origin + Eigen::Vector3f(ARROW_LENGTH, 0.0f, 0.0f))
243 .width(arrowWidth);
244 layerInteract.add(arrowX);
245
246 viz::Arrow arrowY =
247 viz::Arrow("ArrowY")
248 .color(viz::Color::green())
249 .fromTo(origin, origin + Eigen::Vector3f(0.0f, ARROW_LENGTH, 0.0f))
250 .width(arrowWidth);
251 layerInteract.add(arrowY);
252
253 viz::Arrow arrowZ =
254 viz::Arrow("ArrowZ")
255 .color(viz::Color::blue())
256 .fromTo(origin, origin + Eigen::Vector3f(0.0f, 0.0f, ARROW_LENGTH))
257 .width(arrowWidth);
258 layerInteract.add(arrowZ);
259
260
261 layerInteract.add(x.element);
262 layerInteract.add(y.element);
263 layerInteract.add(z.element);
264
265 layerResult = arviz.layer("SlidersResult2");
266 layerResult.add(sphere);
267 }
268
269 void
271 {
272 // Let the Transformable<T> handle all events internally
273 bool needsLayerUpdate = false;
274 viz::TransformationResult xResult = x.handle(interaction);
275 needsLayerUpdate |= xResult.needsLayerUpdate;
276 needsLayerUpdate |= y.handle(interaction).needsLayerUpdate;
277 needsLayerUpdate |= z.handle(interaction).needsLayerUpdate;
278 if (needsLayerUpdate)
279 {
280 // At least one Transformable<T> indicated that the layer needs to be updated
281 stage->add(layerInteract);
282 }
283
284 // We could react to specific events
285 if (xResult.wasTransformed)
286 {
287 ARMARX_INFO << "The x slider was transformed: " << x.getCurrentPose().col(3).x();
288 }
289
290 // We handle the transform event ourselves to add custom behavior
291 // Here, we move the sphere based on the position of the sliders
292 if (interaction.type() == viz::InteractionFeedbackType::Transform)
293 {
294 // We can query getCurrentPose() to determine the poses of the sliders
295 // with the transformation applied to them
296 Eigen::Vector3f spherePosition(x.getCurrentPose().col(3).x(),
297 y.getCurrentPose().col(3).y(),
298 z.getCurrentPose().col(3).z());
299 sphere.position(spherePosition);
300
301 stage->add(layerResult);
302 }
303 }
304
305 Eigen::Vector3f origin;
309
311
314 };
315 // ---------------
316
317
318 enum class SpawnerType
319 {
323 };
324
325 enum class SpawnerOption
326 {
329 };
330
331 struct Spawner
332 {
334
335 Eigen::Vector3f position = Eigen::Vector3f::Zero();
336 float size = 100.0f;
337 viz::Color color = viz::Color::black();
338
339 void
340 visualize(int i, viz::Layer& layer)
341 {
342 viz::InteractionDescription interaction =
344 {"Delete All", "Delete All of Type"});
345 std::string name = "Spawner_" + std::to_string(i);
346 switch (type)
347 {
348 case SpawnerType::Box:
349 {
351 interaction);
352 layer.add(box);
353 }
354 break;
356 {
357 viz::Cylinder cylinder = viz::Cylinder(name)
359 .radius(size * 0.5f)
360 .height(size)
361 .color(color)
362 .enable(interaction);
363 layer.add(cylinder);
364 }
365 break;
367 {
368 viz::Sphere sphere = viz::Sphere(name)
370 .radius(size * 0.5f)
371 .color(color)
372 .enable(interaction);
373 layer.add(sphere);
374 }
375 break;
376 }
377 }
378 };
379
381 {
382 int index = 0;
383 Spawner* source = nullptr;
384 Eigen::Matrix4f transform = Eigen::Matrix4f::Identity();
385 Eigen::Vector3f scale = Eigen::Vector3f::Ones();
386
387 void
389 {
390 if (source == nullptr)
391 {
392 ARMARX_WARNING << "Tried to visualize a spawned object that does not have a source";
393 return;
394 }
395
396 viz::InteractionDescription interaction =
397 viz::interaction().selection().contextMenu({"Delete"});
398 std::string name = "Object_" + std::to_string(index);
399
400 Eigen::Matrix4f initial = Eigen::Matrix4f::Identity();
401 initial.block<3, 1>(0, 3) = source->position;
402 Eigen::Matrix4f pose = transform * initial;
403
404 switch (source->type)
405 {
406 case SpawnerType::Box:
407 {
408 viz::Box box = viz::Box(name)
409 .pose(pose)
410 .scale(scale)
411 .size(source->size)
412 .color(source->color)
413 .enable(interaction);
414 layer.add(box);
415 }
416 break;
418 {
419 viz::Cylinder cylinder = viz::Cylinder(name)
420 .pose(pose)
421 .scale(scale)
422 .radius(source->size * 0.5f)
423 .height(source->size)
424 .color(source->color)
425 .enable(interaction);
426 layer.add(cylinder);
427 }
428 break;
430 {
431 viz::Sphere sphere = viz::Sphere(name)
432 .pose(pose)
433 .scale(scale)
434 .radius(source->size * 0.5f)
435 .color(source->color)
436 .enable(interaction);
437 layer.add(sphere);
438 }
439 break;
440 }
441 }
442 };
443
445 {
446 SpawnersState(Eigen::Vector3f origin) : origin(origin)
447 {
448 float size = 100.0f;
449 {
450 Spawner& spawner = spawners.emplace_back();
451 spawner.type = SpawnerType::Box;
452 spawner.position = origin + Eigen::Vector3f(750.0f, 500.0f, 0.5f * size);
453 spawner.color = viz::Color::cyan();
454 }
455 {
456 Spawner& spawner = spawners.emplace_back();
457 spawner.type = SpawnerType::Cylinder;
458 spawner.position = origin + Eigen::Vector3f(1250.0f, 500.0f, 0.5f * size);
459 spawner.color = viz::Color::magenta();
460 }
461 {
462 Spawner& spawner = spawners.emplace_back();
463 spawner.type = SpawnerType::Sphere;
464 spawner.position = origin + Eigen::Vector3f(1000.0f, 750.0f, 0.5f * size);
465 spawner.color = viz::Color::yellow();
466 }
467 }
468
469 void
471 {
472 layerSpawners = arviz.layer("Spawners");
473
474 int index = 0;
475 for (Spawner& spawner : spawners)
476 {
477 spawner.visualize(index, layerSpawners);
478 index += 1;
479 }
480
481 layerObjects = arviz.layer("SpawnedObjects");
482 }
483
484 void
486 {
487 layerObjects.clear();
488 for (auto& object : objects)
489 {
490 object.visualize(layerObjects);
491 }
492 stage->add(layerObjects);
493 }
494
495 void
497 {
498 Spawner* spawner = nullptr;
499 for (int i = 0; i < (int)spawners.size(); ++i)
500 {
501 std::string name = "Spawner_" + std::to_string(i);
502 if (interaction.element() == name)
503 {
504 spawner = &spawners[i];
505 break;
506 }
507 }
508 if (spawner == nullptr)
509 {
510 ARMARX_INFO << "No spawner" << interaction.element();
511 // A spawned object was selected instead of a spawner
512 if (interaction.type() == viz::InteractionFeedbackType::ContextMenuChosen &&
513 interaction.chosenContextMenuEntry() == 0)
514 {
515 // The delete context menu option was chosen
516 // So we remove the object from the internal list and redraw
517 auto newEnd = std::remove_if(objects.begin(),
518 objects.end(),
519 [&interaction](SpawnedObject const& object)
520 {
521 std::string name =
522 "Object_" + std::to_string(object.index);
523 return interaction.element() == name;
524 });
525 objects.erase(newEnd, objects.end());
526
528 }
529 return;
530 }
531
532 switch (interaction.type())
533 {
535 {
536 // Create a spawned object
538 spawnedObject.source = spawner;
539 spawnedObject.transform = Eigen::Matrix4f::Identity();
540 spawnedObject.scale.setOnes();
541 }
542 break;
543
545 {
546 // Update state of spawned object
547 spawnedObject.transform = interaction.transformation();
548 spawnedObject.scale = interaction.scale();
549 if (interaction.isTransformBegin())
550 {
551 // Visualize all other objects except the currently spawned one
553 }
554 if (interaction.isTransformEnd())
555 {
556 spawnedObject.visualize(layerObjects);
557 stage->add(layerObjects);
558 }
559 }
560 break;
561
563 {
564 // Save state of spawned object
565 objects.push_back(spawnedObject);
566 }
567 break;
568
570 {
571 SpawnerOption option = (SpawnerOption)(interaction.chosenContextMenuEntry());
572 switch (option)
573 {
575 {
576 objects.clear();
577 layerObjects.clear();
578
579 stage->add(layerObjects);
580 }
581 break;
583 {
584 auto newEnd = std::remove_if(objects.begin(),
585 objects.end(),
586 [spawner](SpawnedObject const& obj)
587 { return obj.source == spawner; });
588 objects.erase(newEnd, objects.end());
589
591 }
592 break;
593 }
594 }
595
596 default:
597 {
598 // Ignore other interaction types
599 }
600 break;
601 }
602 }
603
604 Eigen::Vector3f origin;
605
606 std::vector<Spawner> spawners;
609 std::vector<SpawnedObject> objects;
610
613 };
614
615 /**
616 * @defgroup Component-ArVizInteractExample ArVizInteractExample
617 * @ingroup RobotAPI-Components
618 *
619 * An example for how to visualize 3D elements via the 3D visualization
620 * framework ArViz.
621 *
622 * The example creates several layers, fills them with visualization
623 * elements, and commits them to ArViz.
624 *
625 * To see the result:
626 * \li Start the component `ArVizStorage`
627 * \li Open the gui plugin `ArViz`
628 * \li Start the component `ArVizInteractExample`
629 *
630 * The scenario `ArVizInteractExample` starts the necessary components,
631 * including the example component.
632 *
633 *
634 * A component which wants to visualize data via ArViz should:
635 * \li `#include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>`
636 * \li Inherit from the `armarx::ArVizComponentPluginUser`. This adds the
637 * necessary properties (e.g. the topic name) and provides a
638 * ready-to-use ArViz client called `arviz`.
639 * \li Use the inherited ArViz client variable `arviz` of type `viz::Client`
640 * to create layers, add visualization elements to the layers,
641 * and commit the layers to the ArViz topic.
642 *
643 * \see ArVizInteractExample
644 *
645 *
646 * @class ArVizInteractExample
647 * @ingroup Component-ArVizInteractExample
648 *
649 * @brief An example for how to use ArViz.
650 *
651 * @see @ref Component-ArVizInteractExample
652 */
654 virtual armarx::Component,
655 // Deriving from armarx::ArVizComponentPluginUser adds necessary properties
656 // and provides a ready-to-use ArViz client called `arviz`.
658 {
659 std::string
660 getDefaultName() const override
661 {
662 return "ArVizInteractExample";
663 }
664
672
673 void
675 {
676 }
677
678 void
680 {
682 task->start();
683 }
684
685 void
687 {
688 const bool join = true;
689 task->stop(join);
690 task = nullptr;
691 }
692
693 void
695 {
696 }
697
698 void
700 {
701 viz::StagedCommit stage;
702
703 viz::Layer regions = arviz.layer("Regions");
704 Eigen::Vector3f origin1(-2000.0f, 0.0f, 0.0f);
705 Eigen::Vector3f origin2(0.0f, 0.0f, 0.0f);
706 Eigen::Vector3f origin3(-2000.0f, -2000.0f, 0.0f);
707 Eigen::Vector3f origin4(0.0f, -2000.0f, 0.0f);
708 {
709 viz::Cylinder separatorX =
710 viz::Cylinder("SeparatorX")
711 .fromTo(origin1, origin1 + 4000.0f * Eigen::Vector3f::UnitX())
712 .radius(5.0f);
713 regions.add(separatorX);
714
715 viz::Cylinder separatorY =
716 viz::Cylinder("SeparatorY")
717 .fromTo(origin4, origin4 + 4000.0f * Eigen::Vector3f::UnitY())
718 .radius(5.0f);
719 regions.add(separatorY);
720
721 stage.add(regions);
722 }
723
724
725 SlidersState sliders(origin1 + Eigen::Vector3f(500.0f, 500.0f, 0.0f));
726 SlidersState2 sliders2(origin3 + Eigen::Vector3f(500.0f, 500.0f, 0.0f));
727 SpawnersState spawners(origin2);
728
729 sliders.visualize(arviz);
730 stage.add(sliders.layerInteract);
731 stage.add(sliders.layerResult);
732
733 sliders2.visualize(arviz);
734 stage.add(sliders2.layerInteract);
735 stage.add(sliders2.layerResult);
736
737 spawners.visualize(arviz);
738 stage.add(spawners.layerSpawners);
739 stage.add(spawners.layerObjects);
740
741 viz::CommitResult result = arviz.commit(stage);
742 ARMARX_INFO << "Initial commit at revision: " << result.revision();
743
744 CycleUtil c(10.0f);
745 while (!task->isStopped())
746 {
747 result = arviz.commit(stage);
748
749 // Reset the stage, so that it can be rebuild during the interaction handling
750 stage.reset();
751
752 stage.requestInteraction(sliders.layerInteract);
753 stage.requestInteraction(sliders2.layerInteract);
754 stage.requestInteraction(spawners.layerSpawners);
755 stage.requestInteraction(spawners.layerObjects);
756
757 viz::InteractionFeedbackRange interactions = result.interactions();
758 for (viz::InteractionFeedback const& interaction : interactions)
759 {
760 if (interaction.layer() == "Sliders")
761 {
762 sliders.handle(interaction, &stage);
763 }
764 if (interaction.layer() == "Sliders2")
765 {
766 sliders2.handle(interaction, &stage);
767 }
768 if (interaction.layer() == "Spawners" ||
769 interaction.layer() == "SpawnedObjects")
770 {
771 spawners.handle(interaction, &stage);
772 }
773 }
774
775 c.waitForCycleDuration();
776 }
777 }
778
780 };
781
783} // namespace armarx
784
785int
786main(int argc, char* argv[])
787{
788 return armarx::DecoupledMain(argc, argv);
789}
#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
int DecoupledMain(int argc, char *argv[])
Definition Decoupled.cpp:48
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