8 #include <Inventor/SoPath.h>
11 #include <Eigen/Geometry>
20 static const int ANY_TRANSFORM = data::InteractionEnableFlags::TRANSLATION_X |
21 data::InteractionEnableFlags::TRANSLATION_Y |
22 data::InteractionEnableFlags::TRANSLATION_Z |
23 data::InteractionEnableFlags::ROTATION_X |
24 data::InteractionEnableFlags::ROTATION_Y |
25 data::InteractionEnableFlags::ROTATION_Z |
26 data::InteractionEnableFlags::SCALING_X |
27 data::InteractionEnableFlags::SCALING_Y |
28 data::InteractionEnableFlags::SCALING_Z;
45 static void selectionCallback(
void*
data, SoPath* path)
47 CoinVisualizer* this_ =
static_cast<CoinVisualizer*
>(
data);
48 this_->onSelectEvent(path, data::InteractionFeedbackType::SELECT);
51 static void deselectionCallback(
void*
data, SoPath* path)
53 CoinVisualizer* this_ =
static_cast<CoinVisualizer*
>(
data);
54 this_->onSelectEvent(path, data::InteractionFeedbackType::DESELECT);
57 static void startManipulationCallback(
void*
data, SoDragger* dragger)
59 CoinVisualizer* this_ =
static_cast<CoinVisualizer*
>(
data);
60 this_->onManipulation(dragger, data::InteractionFeedbackType::TRANSFORM_BEGIN_FLAG);
63 static void duringManipulationCallback(
void*
data, SoDragger* dragger)
65 CoinVisualizer* this_ =
static_cast<CoinVisualizer*
>(
data);
66 this_->onManipulation(dragger, data::InteractionFeedbackType::TRANSFORM_DURING_FLAG);
69 static void finishManipulationCallback(
void*
data, SoDragger* dragger)
71 CoinVisualizer* this_ =
static_cast<CoinVisualizer*
>(
data);
72 this_->onManipulation(dragger, data::InteractionFeedbackType::TRANSFORM_END_FLAG);
104 << diff.toMilliSecondsDouble() <<
" ms";
109 const char*
function;
126 selection->addSelectionCallback(&selectionCallback,
this);
127 selection->addDeselectionCallback(&deselectionCallback,
this);
130 root =
new SoSeparator;
151 std::unique_lock<std::mutex> lock(
stateMutex);
155 <<
"Expected: STOPPED\n"
184 timing.
addLayer = time_addLayer - time_start;
199 timing.
total = time_end - time_start;
208 if (layerIt ==
layers.
data.end() || layerIt->id != layerID)
211 SoSeparator* coinNode =
new SoSeparator;
216 layerIt->elements.reserve(64);
225 for (viz::data::ElementPtr
const& updatedElementPtr :
update.elements)
227 if (!updatedElementPtr)
233 data::Element
const& updatedElement = *updatedElementPtr;
235 std::type_index elementType =
typeid(updatedElement);
238 for (visuIndex = 0; visuIndex < visuSize; ++visuIndex)
245 if (visuIndex >= visuSize)
248 <<
"No visualizer for element type found: "
254 auto oldElementIter = layer->
lowerBound(updatedElement.id);
256 if (oldElementIter != layer->
elements.end() && oldElementIter->data->id == updatedElement.id)
264 bool updated = visualizer->
update(updatedElement, &oldElementVisu);
269 viz::data::InteractionDescription& oldInteraction = oldElement->
data->interaction;
270 viz::data::InteractionDescription& newInteraction = updatedElementPtr->interaction;
271 if (newInteraction.enableFlags != oldInteraction.enableFlags
272 || oldInteraction.contextMenuOptions != newInteraction.contextMenuOptions)
277 oldElement->
data = updatedElementPtr;
287 auto elementVisu = visualizer->
create(updatedElement);
288 if (elementVisu->separator)
291 viz::data::InteractionDescription& newInteraction = updatedElementPtr->interaction;
292 if (newInteraction.enableFlags != 0)
297 layer->
node->addChild(elementVisu->separator);
300 oldElement->
data = updatedElementPtr;
301 oldElement->
visu = std::move(elementVisu);
313 <<
"CoinElementVisualizer returned null for type: " << typeName <<
"\n"
314 <<
"You need to register a visualizer for each type in ArViz/Coin/RegisterVisualizationTypes.cpp";
320 data::InteractionDescription
const& interactionDesc,
333 if (foundInteraction ==
nullptr)
339 foundInteraction->
layer = layerID;
340 foundInteraction->
element = elementID;
343 foundInteraction->
visu = visu;
346 visu->
separator->setUserData(foundInteraction);
347 visu->
separator->setName(
"InteractiveNode");
362 void* userData = elementVisu.
separator->getUserData();
367 [userData](std::unique_ptr<ElementInteractionData>
const& entry)
369 return entry.get() == userData;
380 elementVisu.
separator->setUserData(
nullptr);
399 std::unique_lock<std::mutex> lock(
stateMutex);
440 storage->begin_pullUpdatesSinceAndSendInteractions(
449 timing.
pull = time_pull - time_start;
451 timing.
applies.reserve(currentUpdates.updates.size());
452 for (data::LayerUpdate
const&
update : currentUpdates.updates)
461 if (layerIDsAfter != layerIDsBefore)
469 timing.
total = time_end - time_start;
492 std::unique_lock<std::mutex> lock(
stateMutex);
517 if (layer ==
nullptr)
555 std::vector<CoinLayerID> result;
559 result.push_back(layer.
id);
600 void* userData =
nullptr;
601 int pathLength = path->getLength();
602 for (
int i = 0; i < pathLength; ++i)
604 SoNode* node = path->getNode(i);
605 const char* name = node->getName().getString();
606 if (strcmp(name,
"InteractiveNode") == 0)
608 userData = node->getUserData();
609 if (userData !=
nullptr)
616 return static_cast<ElementInteractionData*
>(userData);
629 if (eventType == data::InteractionFeedbackType::SELECT)
638 int enableFlags =
id->interaction.enableFlags;
639 if ((enableFlags & data::InteractionEnableFlags::SELECT) == 0)
645 if (eventType == data::InteractionFeedbackType::SELECT)
650 if (enableFlags & ANY_TRANSFORM)
657 dragger->addStartCallback(&startManipulationCallback,
this);
658 dragger->addMotionCallback(&duringManipulationCallback,
this);
659 dragger->addFinishCallback(&finishManipulationCallback,
this);
664 SoSeparator* newSep =
new SoSeparator();
665 int childNum =
id->visu->separator->getNumChildren();
666 for (
int i = 0; i < childNum; ++i)
668 SoNode* child =
id->visu->separator->getChild(i);
669 if (SoSwitch* switch_ =
dynamic_cast<SoSwitch*
>(child))
671 child = switch_->copy();
673 newSep->addChild(child);
678 if (enableFlags & data::InteractionEnableFlags::TRANSFORM_HIDE)
680 id->visu->switch_->whichChild = SO_SWITCH_NONE;
691 if (enableFlags & data::InteractionEnableFlags::TRANSFORM_HIDE)
695 SbMatrix manipMatrix;
699 id->visu->transform->multLeft(manipMatrix);
701 SbVec3f translation =
id->visu->transform->translation.getValue();
702 ARMARX_IMPORTANT <<
"Visu translation: " << translation[0] <<
", " << translation[1] <<
", " << translation[2];
704 id->visu->switch_->whichChild = SO_SWITCH_ALL;
712 feedback.type = eventType;
713 feedback.component =
id->layer.first;
714 feedback.layer =
id->layer.second;
715 feedback.element =
id->element;
721 SbVec3f t_o_scaled(s_m[0] * t_o[0], s_m[1] * t_o[1], s_m[2] * t_o[2]);
722 SbVec3f t_added_rotation_and_scale;
723 r_m.multVec(t_o_scaled, t_added_rotation_and_scale);
724 t_added_rotation_and_scale -= t_o;
726 SbVec3f t_added_rotation;
727 r_m.multVec(t_o, t_added_rotation);
728 t_added_rotation -= t_o;
729 SbVec3f t_added_scale = t_added_rotation_and_scale - t_added_rotation;
730 return t_added_scale;
735 SbVec3f t_o_scaled(s_m[0] * t_o[0], s_m[1] * t_o[1], s_m[2] * t_o[2]);
736 SbVec3f t_added_rotation_and_scale;
737 r_m.multVec(t_o_scaled, t_added_rotation_and_scale);
738 t_added_rotation_and_scale -= t_o;
745 return t_added_rotation_and_scale;
751 for (
int y = 0; y < 4; ++y)
753 for (
int x = 0; x < 4; ++x)
755 result(x, y) = mat[y][x];
763 static SbRotation constrainRotation(SbRotation
input,
int enableFlags)
766 mat.setRotate(
input);
769 Eigen::Vector3f rpy = mat_rot.eulerAngles(0, 1, 2);
771 if ((enableFlags & data::InteractionEnableFlags::ROTATION_X) == 0)
775 if ((enableFlags & data::InteractionEnableFlags::ROTATION_Y) == 0)
779 if ((enableFlags & data::InteractionEnableFlags::ROTATION_Z) == 0)
785 mat_rot = Eigen::AngleAxisf(rpy(0), Eigen::Vector3f::UnitX())
786 * Eigen::AngleAxisf(rpy(1), Eigen::Vector3f::UnitY())
787 * Eigen::AngleAxisf(rpy(2), Eigen::Vector3f::UnitZ());
790 SbRotation result(
q.x(),
q.y(),
q.z(),
q.w());
794 static SbVec3f constrainScaling(SbVec3f
input,
int enableFlags)
796 SbVec3f result =
input;
797 if ((enableFlags & data::InteractionEnableFlags::SCALING_X) == 0)
801 if ((enableFlags & data::InteractionEnableFlags::SCALING_Y) == 0)
805 if ((enableFlags & data::InteractionEnableFlags::SCALING_Z) == 0)
820 ARMARX_WARNING <<
"A manipulation event was fired but no element is selected";
826 viz::data::InteractionFeedback* newFeedback =
nullptr;
829 if ((feedback.type & 0x7) == data::InteractionFeedbackType::TRANSFORM
835 newFeedback = &feedback;
836 newFeedback->type |= eventType;
839 if (newFeedback ==
nullptr)
846 newFeedback->type = data::InteractionFeedbackType::TRANSFORM | eventType;
854 SbRotation r_m_old =
manipulator->rotation.getValue();
855 SbVec3f s_m_old =
manipulator->scaleFactor.getValue();
859 SbRotation r_m = constrainRotation(r_m_old, enableFlags);
860 SbVec3f s_m = constrainScaling(s_m_old, enableFlags);
873 SbVec3f t_diff = t_new - t_old;
883 SbVec3f t_diff = t_new - t_old;
895 SbVec3f t_o_scaled(s_m[0] * t_o[0], s_m[1] * t_o[1], s_m[2] * t_o[2]);
896 SbVec3f t_added_rotation_and_scale;
897 r_m.multVec(t_o_scaled, t_added_rotation_and_scale);
898 t_added_rotation_and_scale -= t_o;
899 SbVec3f delta_t = t_added_rotation_and_scale + t_m;
901 SbVec3f t_added_rotation;
902 r_m.multVec(t_o, t_added_rotation);
903 t_added_rotation -= t_o;
904 SbVec3f t_added_scale = t_added_rotation_and_scale - t_added_rotation;
907 if ((enableFlags & data::InteractionEnableFlags::TRANSLATION_X) == 0)
911 if ((enableFlags & data::InteractionEnableFlags::TRANSLATION_Y) == 0)
915 if ((enableFlags & data::InteractionEnableFlags::TRANSLATION_Z) == 0)
920 SbVec3f t_m_projected = delta_t - t_added_rotation_and_scale;
925 SbVec3f t_m_non_scaled = t_m_projected + t_added_scale;
927 data::GlobalPose& transformation = newFeedback->transformation;
928 transformation.x = 1000.0f * t_m_non_scaled[0];
929 transformation.y = 1000.0f * t_m_non_scaled[1];
930 transformation.z = 1000.0f * t_m_non_scaled[2];
931 transformation.qw = r_m[3];
932 transformation.qx = r_m[0];
933 transformation.qy = r_m[1];
934 transformation.qz = r_m[2];
936 armarx::Vector3f& scale = newFeedback->scale;