Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
SlideNode.cpp
Go to the documentation of this file.
1/*
2 This source file is part of Rigs of Rods
3 Copyright 2005-2012 Pierre-Michel Ricordel
4 Copyright 2007-2012 Thomas Fischer
5 Copyright 2009 Christopher Ritchey
6 Copyright 2018 Petr Ohlidal
7
8 For more information, see http://www.rigsofrods.org/
9
10 Rigs of Rods is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 3, as
12 published by the Free Software Foundation.
13
14 Rigs of Rods is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
21*/
22
26
27#include "SlideNode.h"
28
29#include "Actor.h"
30#include "Application.h"
31#include "SimData.h"
32
33using namespace RoR;
34
51Ogre::Vector3 NearestPointOnLine(const Ogre::Vector3& pt1, const Ogre::Vector3& pt2, const Ogre::Vector3& tp)
52{
53 Ogre::Vector3 a = tp - pt1;
54 Ogre::Vector3 b = pt2 - pt1;
55 Ogre::Real len = b.normalise();
56
57 len = std::max(0.0f, std::min(a.dotProduct(b), len));
58
59 return pt1 + b * len;
60}
61
62// SLIDE NODES IMPLEMENTATION //////////////////////////////////////////////////
63SlideNode::SlideNode(node_t* slidingNode, RailGroup* slidingRail):
64
65 m_sliding_node(slidingNode),
66 m_sliding_beam(NULL),
67 m_initial_railgroup(slidingRail),
68 m_cur_railgroup(m_initial_railgroup),
69 m_cur_rail_seg(NULL),
70 m_node_forces_ratio(0.0f),
71
72 m_initial_threshold(0.0f),
73 m_cur_threshold(0.0f),
74 m_spring_rate(9000000),
75 m_break_force(std::numeric_limits<Ogre::Real>::infinity()), // beam won't break
76
77 m_attach_rate(1.0f),
78 m_attach_distance(0.1f),
79 sn_attach_foreign(false),
80 sn_attach_self(false),
81 sn_slide_broken(false)
82{
83 // make sure they exist
85}
86
88{
89 // only do calcs if we have a beam to slide on
91 {
92 return;
93 }
94
95 // the threshold changes when attaching a node to a beam, if it's more than
96 // the initial amount then then we're still attaching.
98 {
100 }
101
102 Ogre::Vector3 perpForces = this->CalcCorrectiveForces();
103 // perpendicular Forces are distributed according to the position along the Beam
104 if (perpForces.length() > m_break_force)
105 {
106 sn_slide_broken = true;
107 }
108
109 m_sliding_node->Forces += -perpForces;
110 m_sliding_beam->p1->Forces += perpForces * (1 - m_node_forces_ratio);
112}
113
114RailSegment* RailGroup::FindClosestSegment(const Ogre::Vector3& point)
115{
116 float closest_dist_sq = SlideNode::getLenTo(&this->rg_segments[0], point);
117 size_t closest_seg = 0;
118
119 for (size_t i = 1; i < this->rg_segments.size(); ++i)
120 {
121 const float dist_sq = SlideNode::getLenTo(&this->rg_segments[i], point);
122 if (dist_sq < closest_dist_sq)
123 {
124 closest_dist_sq = dist_sq;
125 closest_seg = i;
126 }
127 }
128
129 return &this->rg_segments[closest_seg];
130}
131
133{
134 float closest_dist_sq = SlideNode::getLenTo(this, point);
135 RailSegment* closest_seg = this;
136
137 if (this->rs_prev != nullptr)
138 {
139 const float dist_sq = SlideNode::getLenTo(this->rs_prev, point);
140 if (dist_sq < closest_dist_sq)
141 {
142 closest_seg = this->rs_prev;
143 closest_dist_sq = dist_sq;
144 }
145 }
146
147 if (this->rs_next != nullptr)
148 {
149 const float dist_sq = SlideNode::getLenTo(this->rs_next, point);
150 if (dist_sq < closest_dist_sq)
151 {
152 closest_seg = this->rs_next;
153 }
154 }
155
156 return closest_seg;
157}
158
160{
161 return m_sliding_node->pos;
162}
163
165{
166 // only do calcs if we have a beam to slide on
168 {
170 return;
171 }
172
173 // find which beam to use
176
177 // Get vector for beam
179
180 // pre-compute normal
181 const Ogre::Real bLen = b.normalise();
182
183 // Get dot product along the b beam
184 const Ogre::Real aDotBUnit = (m_sliding_node->AbsPosition - m_sliding_beam->p1->AbsPosition).dotProduct(b);
185
186 // constrain Value between the two end points
187 const Ogre::Real len = std::max(0.0f, std::min(aDotBUnit, bLen));
189
190 // calculate(cache) the ratio between the the two end points,
191 // if bLen = 0.0f it means the beam is zero length so pick an end point
192 m_node_forces_ratio = (bLen > 0.0f) ? len / bLen : 0.0f;
193}
194
195const Ogre::Vector3& SlideNode::GetSlideNodePosition() const
196{
198}
199
209
210Ogre::Real SlideNode::getLenTo(const RailGroup* group, const Ogre::Vector3& point)
211{
212 if (!group)
213 return std::numeric_limits<Ogre::Real>::infinity();
214
215 return getLenTo(&group->rg_segments[0], point);
216}
217
218Ogre::Real SlideNode::getLenTo(const RailSegment* rail, const Ogre::Vector3& point)
219{
220 if (!rail)
221 return std::numeric_limits<Ogre::Real>::infinity();
222
223 return getLenTo(rail->rs_beam, point);
224}
225
226Ogre::Real SlideNode::getLenTo(const beam_t* beam, const Ogre::Vector3& point)
227{
228 if (!beam)
229 return std::numeric_limits<Ogre::Real>::infinity();
230
231 return (NearestPointOnLine(beam->p1->AbsPosition, beam->p2->AbsPosition, point) - point).length();
232}
233
234Ogre::Real SlideNode::getLenTo(const RailGroup* group) const
235{
236 return getLenTo(group, m_sliding_node->AbsPosition);
237}
238
239Ogre::Real SlideNode::getLenTo(const RailSegment* rail) const
240{
241 return getLenTo(rail, m_sliding_node->AbsPosition);
242}
243
244Ogre::Real SlideNode::getLenTo(const beam_t* beam) const
245{
246 return getLenTo(beam, m_sliding_node->AbsPosition);
247}
248
250{
251 Ogre::Vector3 force = (m_ideal_position - m_sliding_node->AbsPosition);
252 const Ogre::Real beamLen = std::max(0.0f, force.normalise() - m_cur_threshold);
253 const Ogre::Real forceLen = -m_spring_rate * beamLen;
254 return (force * forceLen);
255}
Central state/object manager and communications hub.
#define ROR_ASSERT(_EXPR)
Definition Application.h:40
Core data structures for simulation; Everything affected by by either physics, network or user intera...
Ogre::Vector3 NearestPointOnLine(const Ogre::Vector3 &pt1, const Ogre::Vector3 &pt2, const Ogre::Vector3 &tp)
Find the point on a line defined by pt1 and pt2 that is nearest to a given point tp tp /| A / | / | /...
Definition SlideNode.cpp:51
void UpdateForces(float dt)
Updates the corrective forces and applies these forces to the beam.
Definition SlideNode.cpp:87
SlideNode(node_t *sliding_node, RailGroup *rail)
Definition SlideNode.cpp:63
int GetSlideNodeId()
Returns the node index of the slide node.
void ResetPositions()
Recalculates the closest position on current RailGroup.
RailGroup * m_cur_railgroup
Current Rail group, used for attachments.
Definition SlideNode.h:117
float m_attach_rate
How fast the cur threshold changes when attaching (i.e. how long it will take for springs to fully at...
Definition SlideNode.h:125
Ogre::Vector3 m_ideal_position
Where the node SHOULD be. (World, m)
Definition SlideNode.h:120
void UpdatePosition()
Checks for current rail segment and updates ideal position of the node.
float m_initial_threshold
Distance from beam calculating corrective forces (m)
Definition SlideNode.h:121
float m_spring_rate
Spring rate holding node to rail (N/m)
Definition SlideNode.h:123
bool sn_slide_broken
The slidenode was pulled away from the rail.
Definition SlideNode.h:108
float m_cur_threshold
Distance away from beam before corrective forces begin to act on the node (m)
Definition SlideNode.h:122
Ogre::Vector3 CalcCorrectiveForces()
Calculate forces between the ideal and actual position of the sliding node.
node_t * m_sliding_node
Pointer to node that is sliding.
Definition SlideNode.h:114
beam_t * m_sliding_beam
Pointer to current beam sliding on.
Definition SlideNode.h:115
RailSegment * m_cur_rail_seg
Current rail segment we are sliding on.
Definition SlideNode.h:118
float m_break_force
Force at which Slide Node breaks away from the rail (N)
Definition SlideNode.h:124
static Ogre::Real getLenTo(const RailGroup *group, const Ogre::Vector3 &point)
float m_node_forces_ratio
Ratio of length along the slide beam where the virtual node is "0.0f = p1, 1.0f = p2".
Definition SlideNode.h:119
const Ogre::Vector3 & GetSlideNodePosition() const
A series of RailSegment-s for SlideNode to slide along. Can be closed in a loop.
Definition SlideNode.h:54
RailSegment * FindClosestSegment(Ogre::Vector3 const &point)
Search for closest rail segment (the one with closest node in it) in the entire RailGroup.
std::vector< RailSegment > rg_segments
Definition SlideNode.h:60
A single beam in a chain.
Definition SlideNode.h:41
RailSegment * rs_prev
Definition SlideNode.h:47
RailSegment * rs_next
Definition SlideNode.h:48
RailSegment * CheckCurSlideSegment(Ogre::Vector3 const &point)
Check if the slidenode should skip to a neighbour rail segment.
beam_t * rs_beam
Definition SlideNode.h:49
Simulation: An edge in the softbody structure.
Definition SimData.h:305
node_t * p1
Definition SimData.h:309
bool bm_broken
Definition SimData.h:326
node_t * p2
Definition SimData.h:310
Physics: A vertex in the softbody structure.
Definition SimData.h:260
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition SimData.h:267
Ogre::Vector3 Forces
Definition SimData.h:269
NodeNum_t pos
This node's index in Actor::ar_nodes array.
Definition SimData.h:277