Skip to content

Commit 3737e63

Browse files
committed
Add real-time MoorDyn mooring line visualization to VSG GUI
1 parent fe534f0 commit 3737e63

15 files changed

Lines changed: 689 additions & 2 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ if(HYDROCHRONO_ENABLE_VSG)
509509
src/gui/vsg_gui_component.cpp
510510
src/gui/vsg_lighting.cpp
511511
src/gui/vsg_materials.cpp
512+
src/gui/vsg_mooring_lines.cpp
512513
src/gui/vsg_water_surface.cpp
513514
src/gui/vsg_radiation_surface.cpp
514515
)
@@ -517,6 +518,7 @@ if(HYDROCHRONO_ENABLE_VSG)
517518
src/gui/vsg_gui_component.h
518519
src/gui/vsg_lighting.h
519520
src/gui/vsg_materials.h
521+
src/gui/vsg_mooring_lines.h
520522
src/gui/vsg_water_surface.h
521523
src/gui/vsg_radiation_surface.h
522524
)

demos/rm3/demo_rm3_mooring.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ int main(int argc, char* argv[]) {
135135
ui.SetCamera(0, -50, -10, 0, 0, -10);
136136
ui.SetWaveModel(my_hydro_inputs);
137137

138+
#ifdef HYDROCHRONO_HAVE_MOORDYN
139+
ui.SetMooringLineProvider([&hydro_forces]() {
140+
return hydro_forces.GetMooringLineStates();
141+
});
142+
#endif
143+
138144
while (system.GetChTime() <= simulationDuration) {
139145
if (ui.IsRunning(timestep) == false) break;
140146

include/hydroc/gui/guihelper.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <hydroc/gui/mooring_viz_data.h>
4+
35
#include <memory>
46

57
namespace chrono {
@@ -61,6 +63,14 @@ class UI {
6163
virtual void SetWaterGridExtent(double width, double length,
6264
double center_x = 0.0, double center_y = 0.0);
6365

66+
/**@brief Set a callback that provides mooring line node positions each frame.
67+
*
68+
* When set, the GUI will call the provider every frame to obtain line
69+
* geometry and render tube meshes for each mooring line.
70+
* Call after Init() and before the simulation loop.
71+
*/
72+
virtual void SetMooringLineProvider(MooringVizProvider provider);
73+
6474
/**@brief return the internal system.
6575
*
6676
* Should be called after init.
@@ -90,6 +100,7 @@ class GUI : public UI {
90100
void SetWaveModel(std::shared_ptr<WaveBase> wave) override;
91101
void SetWaterGridExtent(double width, double length,
92102
double center_x = 0.0, double center_y = 0.0) override;
103+
void SetMooringLineProvider(MooringVizProvider provider) override;
93104

94105
private:
95106
std::shared_ptr<hydroc::gui::GUIImpl> pImpl;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/// @file mooring_viz_data.h
2+
/// @brief Lightweight data types for mooring-line visualization.
3+
///
4+
/// Header-only with no MoorDyn or Eigen dependencies so that both the
5+
/// physics library (HydroChrono) and the visualization library
6+
/// (HydroChronoGUI) can include it without pulling in heavy headers.
7+
#pragma once
8+
9+
#include <array>
10+
#include <functional>
11+
#include <vector>
12+
13+
namespace hydroc {
14+
namespace gui {
15+
16+
/// MoorDyn connection-point classification.
17+
/// Values intentionally match the MoorDyn C API convention.
18+
enum class MooringPointType : int {
19+
kCoupled = -1, ///< Vessel fairlead (driven by the coupled body).
20+
kFree = 0, ///< Free point / clump weight / buoy.
21+
kFixed = 1, ///< Seabed anchor or fixed attachment.
22+
};
23+
24+
/// Sentinel value used for intermediate (non-endpoint) node markers.
25+
inline constexpr int kIntermediateNode = -99;
26+
27+
/// Per-line visualization payload: ordered node positions along the line
28+
/// plus the MoorDyn point type at each endpoint.
29+
struct MooringLineVizData {
30+
std::vector<std::array<double, 3>> node_positions;
31+
MooringPointType start_point_type = MooringPointType::kFree;
32+
MooringPointType end_point_type = MooringPointType::kFree;
33+
};
34+
35+
/// Callback the GUI invokes each frame to fetch current line geometry.
36+
using MooringVizProvider = std::function<std::vector<MooringLineVizData>()>;
37+
38+
} // namespace gui
39+
} // namespace hydroc

include/hydroc/hydro_system.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
// MoorDyn mooring configuration
7070
#ifdef HYDROCHRONO_HAVE_MOORDYN
7171
#include <hydroc/config/moordyn_config.h>
72+
#include <hydroc/gui/mooring_viz_data.h>
7273
#endif
7374

7475
namespace hydrochrono::hydro {
@@ -454,6 +455,15 @@ class HydroSystem {
454455
void SetMoorDynConfig(const MoorDynConfig& config) {
455456
moordyn_config_ = config;
456457
}
458+
459+
/**
460+
* @brief Get current mooring line node positions for visualization.
461+
*
462+
* Returns one entry per MoorDyn line, each containing the ordered node
463+
* positions along the line. Returns an empty vector when MoorDyn is
464+
* not active or no lines exist.
465+
*/
466+
std::vector<hydroc::gui::MooringLineVizData> GetMooringLineStates() const;
457467
#endif
458468

459469
/**

src/gui/guihelper.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ void UI::SetWaterGridExtent(double /*width*/, double /*length*/,
3838
// Default (headless) UI does not render water surface.
3939
}
4040

41+
void UI::SetMooringLineProvider(MooringVizProvider /*provider*/) {
42+
// Default (headless) UI does not render mooring lines.
43+
}
44+
4145
// -----------------------------------------------------------------------------
4246

4347
GUI::GUI() {
@@ -72,3 +76,7 @@ void GUI::SetWaveModel(std::shared_ptr<WaveBase> wave) {
7276
void GUI::SetWaterGridExtent(double width, double length, double center_x, double center_y) {
7377
pImpl->SetWaterGridExtent(width, length, center_x, center_y);
7478
}
79+
80+
void GUI::SetMooringLineProvider(MooringVizProvider provider) {
81+
pImpl->SetMooringLineProvider(std::move(provider));
82+
}

src/gui/guihelperVSG.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "vsg_gui_component.h"
1212
#include "vsg_lighting.h"
1313
#include "vsg_materials.h"
14+
#include "vsg_mooring_lines.h"
1415
#include "vsg_radiation_surface.h"
1516
#include "vsg_water_surface.h"
1617

@@ -128,6 +129,10 @@ void GUIImplVSG::SetWaterGridExtent(double width, double length, double center_x
128129
<< ", center: (" << center_x << ", " << center_y << ")" << std::endl;
129130
}
130131

132+
void GUIImplVSG::SetMooringLineProvider(MooringVizProvider provider) {
133+
mooring_provider_ = std::move(provider);
134+
}
135+
131136
void GUIImplVSG::EnsureWaterSurface() {
132137
// Require both system and visual system to be valid.
133138
if (!system_ || !pVis) {
@@ -179,9 +184,30 @@ bool GUIImplVSG::IsRunning(double timestep) {
179184
return false;
180185
}
181186

182-
// Ensure water surface exists (every frame check; returns early if already done).
187+
// Reserve a scene-graph group for mooring geometry before the water
188+
// surface is created, so opaque mooring lines are rendered first and
189+
// remain visible through the transparent free surface.
190+
if (mooring_provider_ && !mooring_scene_group_) {
191+
if (auto scene = pVis->GetVSGScene()) {
192+
mooring_scene_group_ = vsg::Group::create();
193+
scene->addChild(mooring_scene_group_);
194+
}
195+
}
196+
183197
EnsureWaterSurface();
184198

199+
// Mooring line visualisation (lazy-initialised on first valid data).
200+
if (mooring_provider_) {
201+
auto line_data = mooring_provider_();
202+
if (!line_data.empty()) {
203+
if (!mooring_viz_)
204+
mooring_viz_ = std::make_unique<MooringLinesViz>();
205+
if (!mooring_viz_->IsInitializedFor(pVis.get()))
206+
mooring_viz_->Initialize(pVis.get(), line_data, mooring_scene_group_);
207+
mooring_viz_->Update(line_data);
208+
}
209+
}
210+
185211
// Handle viewer settings changes.
186212
if (viewer_settings_ && animated_water_) {
187213
// Handle visibility toggle.

src/gui/guihelper_impl.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class GUIImpl {
4848
virtual void SetWaveModel(std::shared_ptr<WaveBase> /*wave*/) {}
4949
virtual void SetWaterGridExtent(double /*width*/, double /*length*/,
5050
double /*center_x*/, double /*center_y*/) {}
51+
virtual void SetMooringLineProvider(MooringVizProvider /*provider*/) {}
5152
};
5253

5354
#ifdef HYDROCHRONO_HAVE_IRRLICHT
@@ -70,8 +71,9 @@ class GUIImplIRR : public GUIImpl {
7071
#endif
7172

7273
#ifdef HYDROCHRONO_HAVE_VSG
73-
// Forward declarations (defined in vsg_water_surface.h, vsg_gui_component.h).
74+
// Forward declarations (defined in vsg_water_surface.h, vsg_gui_component.h, vsg_mooring_lines.h).
7475
class AnimatedWaterSurface;
76+
class MooringLinesViz;
7577
struct ViewerSettings;
7678

7779
class GUIImplVSG : public GUIImpl {
@@ -86,6 +88,7 @@ class GUIImplVSG : public GUIImpl {
8688
virtual bool IsRunning(double timestep) override;
8789
virtual void SetWaveModel(std::shared_ptr<WaveBase> wave) override;
8890
virtual void SetWaterGridExtent(double width, double length, double center_x, double center_y) override;
91+
virtual void SetMooringLineProvider(MooringVizProvider provider) override;
8992

9093
private:
9194
/// Ensure water surface is created (animated if wave model set, static otherwise).
@@ -100,6 +103,10 @@ class GUIImplVSG : public GUIImpl {
100103
chrono::ChSystem* system_ = nullptr;
101104
std::unique_ptr<AnimatedWaterSurface> animated_water_;
102105
std::unique_ptr<ViewerSettings> viewer_settings_;
106+
107+
MooringVizProvider mooring_provider_;
108+
std::unique_ptr<MooringLinesViz> mooring_viz_;
109+
vsg::ref_ptr<vsg::Group> mooring_scene_group_;
103110
};
104111
#endif
105112

0 commit comments

Comments
 (0)