Skip to content

Commit fcf4cfb

Browse files
authored
Merge branch 'main' into issue/870_unsymmetrical
2 parents e49148d + 323ff7a commit fcf4cfb

34 files changed

+805
-49
lines changed

dart/collision/fcl/FCLCollisionDetector.cpp

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,32 @@
5050
#include "dart/dynamics/PyramidShape.hpp"
5151
#include "dart/dynamics/Shape.hpp"
5252
#include "dart/dynamics/ShapeFrame.hpp"
53+
#include "dart/dynamics/ShapeNode.hpp"
5354
#include "dart/dynamics/SoftMeshShape.hpp"
5455
#include "dart/dynamics/SphereShape.hpp"
5556
#include "dart/dynamics/VoxelGridShape.hpp"
5657

5758
#include <assimp/scene.h>
5859

60+
#include <algorithm>
5961
#include <limits>
62+
#include <string>
63+
64+
#include <cstdint>
6065

6166
namespace dart {
6267
namespace collision {
6368

6469
namespace {
6570

71+
std::string collisionObjectKey(const FCLCollisionObject* object)
72+
{
73+
if (!object)
74+
return "";
75+
76+
return object->getKey();
77+
}
78+
6679
bool collisionCallback(
6780
fcl::CollisionObject* o1, fcl::CollisionObject* o2, void* cdata);
6881

@@ -146,6 +159,11 @@ Contact convertContact(
146159
fcl::CollisionObject* o2,
147160
const CollisionOption& option);
148161

162+
bool shouldSwapDeterministically(
163+
const FCLCollisionObject* fclObj1, const FCLCollisionObject* fclObj2);
164+
165+
void applyDeterministicSwap(Contact& contact);
166+
149167
/// Collision data stores the collision request and the result given by
150168
/// collision algorithm.
151169
struct FCLCollisionCallbackData
@@ -852,6 +870,7 @@ void FCLCollisionDetector::refreshCollisionObject(CollisionObject* const object)
852870

853871
fcl->mFCLCollisionObject = std::unique_ptr<fcl::CollisionObject>(
854872
new fcl::CollisionObject(claimFCLCollisionGeometry(object->getShape())));
873+
fcl->mFCLCollisionObject->setUserData(fcl);
855874
}
856875

857876
//==============================================================================
@@ -1082,16 +1101,16 @@ bool collisionCallback(
10821101
const auto& option = collData->option;
10831102
const auto& filter = option.collisionFilter;
10841103

1085-
// Filtering
1086-
if (filter) {
1087-
auto collisionObject1 = static_cast<FCLCollisionObject*>(o1->getUserData());
1088-
auto collisionObject2 = static_cast<FCLCollisionObject*>(o2->getUserData());
1089-
DART_ASSERT(collisionObject1);
1090-
DART_ASSERT(collisionObject2);
1104+
auto collisionObject1 = static_cast<FCLCollisionObject*>(o1->getUserData());
1105+
auto collisionObject2 = static_cast<FCLCollisionObject*>(o2->getUserData());
1106+
DART_ASSERT(collisionObject1);
1107+
DART_ASSERT(collisionObject2);
1108+
if (!collisionObject1 || !collisionObject2)
1109+
return collData->done;
10911110

1092-
if (filter->ignoresCollision(collisionObject2, collisionObject1))
1093-
return collData->done;
1094-
}
1111+
// Filtering
1112+
if (filter && filter->ignoresCollision(collisionObject2, collisionObject1))
1113+
return collData->done;
10951114

10961115
// Clear previous results
10971116
fclResult.clear();
@@ -1412,6 +1431,15 @@ void postProcessDART(
14121431
} else {
14131432
numContacts++;
14141433
}
1434+
1435+
const auto* fclObj1 = static_cast<FCLCollisionObject*>(o1->getUserData());
1436+
const auto* fclObj2 = static_cast<FCLCollisionObject*>(o2->getUserData());
1437+
if (shouldSwapDeterministically(fclObj1, fclObj2)) {
1438+
if (option.enableContact)
1439+
std::swap(pair1.point, pair2.point);
1440+
applyDeterministicSwap(pair1);
1441+
applyDeterministicSwap(pair2);
1442+
}
14151443
}
14161444

14171445
// For binary check, return after adding the first contact point to the
@@ -1624,10 +1652,8 @@ Contact convertContact(
16241652
{
16251653
Contact contact;
16261654

1627-
contact.collisionObject1
1628-
= static_cast<FCLCollisionObject*>(o1->getUserData());
1629-
contact.collisionObject2
1630-
= static_cast<FCLCollisionObject*>(o2->getUserData());
1655+
contact.collisionObject1 = static_cast<CollisionObject*>(o1->getUserData());
1656+
contact.collisionObject2 = static_cast<CollisionObject*>(o2->getUserData());
16311657

16321658
if (option.enableContact) {
16331659
contact.point = FCLTypes::convertVector3(fclContact.pos);
@@ -1637,9 +1663,40 @@ Contact convertContact(
16371663
contact.triID2 = fclContact.b2;
16381664
}
16391665

1666+
// Enforce deterministic ordering across runs and clones. Tie-break on the
1667+
// underlying FCL object address if keys are identical.
1668+
const auto fclObj1
1669+
= static_cast<FCLCollisionObject*>(contact.collisionObject1);
1670+
const auto fclObj2
1671+
= static_cast<FCLCollisionObject*>(contact.collisionObject2);
1672+
if (shouldSwapDeterministically(fclObj1, fclObj2))
1673+
applyDeterministicSwap(contact);
1674+
16401675
return contact;
16411676
}
16421677

1678+
//==============================================================================
1679+
bool shouldSwapDeterministically(
1680+
const FCLCollisionObject* fclObj1, const FCLCollisionObject* fclObj2)
1681+
{
1682+
const auto key1 = collisionObjectKey(fclObj1);
1683+
const auto key2 = collisionObjectKey(fclObj2);
1684+
1685+
const auto addr1 = reinterpret_cast<std::uintptr_t>(fclObj1);
1686+
const auto addr2 = reinterpret_cast<std::uintptr_t>(fclObj2);
1687+
1688+
return (key2 < key1) || (key1 == key2 && addr2 < addr1 && addr2 != 0u);
1689+
}
1690+
1691+
//==============================================================================
1692+
void applyDeterministicSwap(Contact& contact)
1693+
{
1694+
std::swap(contact.collisionObject1, contact.collisionObject2);
1695+
std::swap(contact.triID1, contact.triID2);
1696+
1697+
contact.normal = -contact.normal;
1698+
}
1699+
16431700
} // anonymous namespace
16441701

16451702
} // namespace collision

dart/collision/fcl/FCLCollisionObject.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@
3434

3535
#include "dart/collision/fcl/FCLTypes.hpp"
3636
#include "dart/common/Macros.hpp"
37+
#include "dart/dynamics/BodyNode.hpp"
3738
#include "dart/dynamics/ShapeFrame.hpp"
39+
#include "dart/dynamics/ShapeNode.hpp"
40+
#include "dart/dynamics/Skeleton.hpp"
3841
#include "dart/dynamics/SoftMeshShape.hpp"
3942

4043
namespace dart {
@@ -63,6 +66,23 @@ FCLCollisionObject::FCLCollisionObject(
6366
mFCLCollisionObject(new dart::collision::fcl::CollisionObject(fclCollGeom))
6467
{
6568
mFCLCollisionObject->setUserData(this);
69+
70+
if (shapeFrame) {
71+
const auto* shapeNode
72+
= dynamic_cast<const dynamics::ShapeNode*>(shapeFrame);
73+
if (shapeNode) {
74+
const auto bodyNode = shapeNode->getBodyNodePtr();
75+
const auto skeleton = bodyNode ? bodyNode->getSkeleton() : nullptr;
76+
77+
if (skeleton)
78+
mKey += skeleton->getName() + "::";
79+
if (bodyNode)
80+
mKey += bodyNode->getName() + "::";
81+
mKey += shapeNode->getName();
82+
} else {
83+
mKey = shapeFrame->getName();
84+
}
85+
}
6686
}
6787

6888
//==============================================================================

dart/collision/fcl/FCLCollisionObject.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include <dart/collision/CollisionObject.hpp>
3737
#include <dart/collision/fcl/BackwardCompatibility.hpp>
3838

39+
#include <string>
40+
3941
namespace dart {
4042
namespace collision {
4143

@@ -50,6 +52,12 @@ class FCLCollisionObject : public CollisionObject
5052
/// Return FCL collision object
5153
const dart::collision::fcl::CollisionObject* getFCLCollisionObject() const;
5254

55+
/// Deterministic key based on the attached ShapeFrame hierarchy.
56+
const std::string& getKey() const
57+
{
58+
return mKey;
59+
}
60+
5361
protected:
5462
/// Constructor
5563
FCLCollisionObject(
@@ -64,6 +72,9 @@ class FCLCollisionObject : public CollisionObject
6472
protected:
6573
/// FCL collision object
6674
std::unique_ptr<dart::collision::fcl::CollisionObject> mFCLCollisionObject;
75+
76+
/// Stable identifier for deterministic ordering.
77+
std::string mKey;
6778
};
6879

6980
} // namespace collision

dart/gui/ImGuiHandler.cpp

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848

4949
#include <algorithm>
5050

51+
#include <cmath>
52+
5153
namespace dart {
5254
namespace gui {
5355

@@ -201,6 +203,29 @@ ConvertedKey convertFromOSGKey(int key)
201203
}
202204
}
203205

206+
//==============================================================================
207+
void applyImGuiScale(float scale)
208+
{
209+
if (!std::isfinite(scale) || scale <= 0.f)
210+
return;
211+
212+
static ImGuiStyle baseStyle
213+
= ImGui::GetStyle(); // capture styled defaults (dark palette)
214+
auto& style = ImGui::GetStyle();
215+
ImGuiIO& io = ImGui::GetIO();
216+
217+
// Reset to the captured base style before applying the requested scale so
218+
// repeated calls are idempotent and preserve the configured palette.
219+
style = baseStyle;
220+
io.FontGlobalScale = 1.f;
221+
222+
if (std::abs(scale - 1.f) < 1e-6f)
223+
return;
224+
225+
style.ScaleAllSizes(scale);
226+
io.FontGlobalScale = scale;
227+
}
228+
204229
//==============================================================================
205230
struct ImGuiNewFrameCallback : public ::osg::Camera::DrawCallback
206231
{
@@ -237,7 +262,10 @@ struct ImGuiDrawCallback : public ::osg::Camera::DrawCallback
237262

238263
//==============================================================================
239264
ImGuiHandler::ImGuiHandler()
240-
: mTime{0.0}, mMousePressed{false, false, false}, mMouseWheel{0.0f}
265+
: mTime{0.0},
266+
mMousePressed{false, false, false},
267+
mMouseWheel{0.0f},
268+
mFramebufferScale{1.0f, 1.0f}
241269
{
242270
ImGui::CreateContext();
243271

@@ -344,6 +372,18 @@ bool ImGuiHandler::handle(
344372
const bool wantCaptureMouse = io.WantCaptureMouse;
345373
const bool wantCaptureKeyboard = io.WantCaptureKeyboard;
346374

375+
const float invScaleX
376+
= mFramebufferScale[0] > 0.0f ? 1.0f / mFramebufferScale[0] : 1.0f;
377+
const float invScaleY
378+
= mFramebufferScale[1] > 0.0f ? 1.0f / mFramebufferScale[1] : 1.0f;
379+
380+
const auto getScaledMousePosition
381+
= [&](const osgGA::GUIEventAdapter& adapter) {
382+
const float scaledX = static_cast<float>(adapter.getX()) * invScaleX;
383+
const float scaledY = static_cast<float>(adapter.getY()) * invScaleY;
384+
return ImVec2(scaledX, io.DisplaySize.y - scaledY);
385+
};
386+
347387
switch (eventAdapter.getEventType()) {
348388
case osgGA::GUIEventAdapter::KEYDOWN: {
349389
const int key = eventAdapter.getUnmodifiedKey();
@@ -417,8 +457,7 @@ bool ImGuiHandler::handle(
417457
return wantCaptureKeyboard;
418458
}
419459
case osgGA::GUIEventAdapter::PUSH: {
420-
io.MousePos
421-
= ImVec2(eventAdapter.getX(), io.DisplaySize.y - eventAdapter.getY());
460+
io.MousePos = getScaledMousePosition(eventAdapter);
422461

423462
if (eventAdapter.getButtonMask()
424463
== osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) {
@@ -440,8 +479,7 @@ bool ImGuiHandler::handle(
440479
}
441480
case osgGA::GUIEventAdapter::DRAG:
442481
case osgGA::GUIEventAdapter::MOVE: {
443-
io.MousePos
444-
= ImVec2(eventAdapter.getX(), io.DisplaySize.y - eventAdapter.getY());
482+
io.MousePos = getScaledMousePosition(eventAdapter);
445483

446484
return wantCaptureMouse;
447485
}
@@ -489,9 +527,39 @@ void ImGuiHandler::newFrame(::osg::RenderInfo& renderInfo)
489527
ImGui_ImplOpenGL2_NewFrame();
490528

491529
auto& io = ImGui::GetIO();
492-
auto* viewport = renderInfo.getCurrentCamera()->getViewport();
530+
auto* camera = renderInfo.getCurrentCamera();
531+
auto* viewport = camera ? camera->getViewport() : nullptr;
532+
533+
ImVec2 displaySize(1.0f, 1.0f);
534+
ImVec2 framebufferScale(1.0f, 1.0f);
535+
536+
if (viewport) {
537+
// Use framebuffer-to-window ratio to honor OS display scaling.
538+
displaySize = ImVec2(viewport->width(), viewport->height());
539+
540+
auto* graphicsContext = camera->getGraphicsContext();
541+
const auto* traits
542+
= graphicsContext ? graphicsContext->getTraits() : nullptr;
543+
if (traits && traits->width > 0 && traits->height > 0) {
544+
framebufferScale.x = static_cast<float>(viewport->width())
545+
/ static_cast<float>(traits->width);
546+
framebufferScale.y = static_cast<float>(viewport->height())
547+
/ static_cast<float>(traits->height);
548+
549+
framebufferScale.x
550+
= framebufferScale.x > 0.0f ? framebufferScale.x : 1.0f;
551+
framebufferScale.y
552+
= framebufferScale.y > 0.0f ? framebufferScale.y : 1.0f;
553+
554+
displaySize = ImVec2(
555+
static_cast<float>(traits->width),
556+
static_cast<float>(traits->height));
557+
}
558+
}
493559

494-
io.DisplaySize = ImVec2(viewport->width(), viewport->height());
560+
io.DisplaySize = displaySize;
561+
io.DisplayFramebufferScale = framebufferScale;
562+
mFramebufferScale = {framebufferScale.x, framebufferScale.y};
495563

496564
const auto currentTime
497565
= renderInfo.getView()->getFrameStamp()->getSimulationTime();

dart/gui/ImGuiHandler.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ namespace gui {
5555

5656
class ImGuiWidget;
5757

58+
DART_GUI_API void applyImGuiScale(float scale);
59+
5860
class DART_GUI_API ImGuiHandler : public osgGA::GUIEventHandler
5961
{
6062
public:
@@ -104,6 +106,8 @@ class DART_GUI_API ImGuiHandler : public osgGA::GUIEventHandler
104106

105107
float mMouseWheel;
106108

109+
std::array<float, 2> mFramebufferScale;
110+
107111
std::vector<std::shared_ptr<ImGuiWidget>> mWidgets;
108112
};
109113

dart/gui/ImGuiViewer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ const ImGuiHandler* ImGuiViewer::getImGuiHandler() const
6868
return mImGuiHandler.get();
6969
}
7070

71+
//==============================================================================
72+
void ImGuiViewer::setImGuiScale(float scale)
73+
{
74+
applyImGuiScale(scale);
75+
}
76+
7177
//==============================================================================
7278
void ImGuiViewer::showAbout()
7379
{

dart/gui/ImGuiViewer.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ class DART_GUI_API ImGuiViewer : public Viewer
6262
/// Get cosnt ImGui handler.
6363
const ImGuiHandler* getImGuiHandler() const;
6464

65+
/// Set the ImGui global scale factor (fonts + widget sizes).
66+
void setImGuiScale(float scale);
67+
6568
/// Show About widget.
6669
void showAbout();
6770

0 commit comments

Comments
 (0)