RigsofRods
Soft-body Physics Simulation
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 
33 using namespace RoR;
34 
51 Ogre::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 //////////////////////////////////////////////////
63 SlideNode::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);
111  m_sliding_beam->p2->Forces += perpForces * m_node_forces_ratio;
112 }
113 
114 RailSegment* 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 
132 RailSegment* RailSegment::CheckCurSlideSegment(const Ogre::Vector3& point)
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
178  Ogre::Vector3 b = m_sliding_beam->p2->AbsPosition - m_sliding_beam->p1->AbsPosition;
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 
195 const Ogre::Vector3& SlideNode::GetSlideNodePosition() const
196 {
197  return m_sliding_node->AbsPosition;
198 }
199 
201 {
202  if (m_cur_railgroup != nullptr)
203  {
206  this->UpdatePosition();
207  }
208 }
209 
210 Ogre::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 
218 Ogre::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 
226 Ogre::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 
234 Ogre::Real SlideNode::getLenTo(const RailGroup* group) const
235 {
236  return getLenTo(group, m_sliding_node->AbsPosition);
237 }
238 
239 Ogre::Real SlideNode::getLenTo(const RailSegment* rail) const
240 {
241  return getLenTo(rail, m_sliding_node->AbsPosition);
242 }
243 
244 Ogre::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 }
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
RoR::SlideNode::m_ideal_position
Ogre::Vector3 m_ideal_position
Where the node SHOULD be. (World, m)
Definition: SlideNode.h:120
RoR::node_t::AbsPosition
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition: SimData.h:294
RoR::SlideNode::m_initial_threshold
float m_initial_threshold
Distance from beam calculating corrective forces (m)
Definition: SlideNode.h:121
RoR::beam_t::p1
node_t * p1
Definition: SimData.h:335
RoR::RailGroup
A series of RailSegment-s for SlideNode to slide along. Can be closed in a loop.
Definition: SlideNode.h:53
RoR::SlideNode::m_spring_rate
float m_spring_rate
Spring rate holding node to rail (N/m)
Definition: SlideNode.h:123
RoR::RailSegment::CheckCurSlideSegment
RailSegment * CheckCurSlideSegment(Ogre::Vector3 const &point)
Check if the slidenode should skip to a neighbour rail segment.
Definition: SlideNode.cpp:132
RoR::SlideNode::m_node_forces_ratio
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
RoR::RailSegment::rs_beam
beam_t * rs_beam
Definition: SlideNode.h:49
RoR::SlideNode::m_cur_railgroup
RailGroup * m_cur_railgroup
Current Rail group, used for attachments.
Definition: SlideNode.h:117
NearestPointOnLine
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
RoR::SlideNode::m_cur_threshold
float m_cur_threshold
Distance away from beam before corrective forces begin to act on the node (m)
Definition: SlideNode.h:122
Actor.h
RoR::RailSegment
A single beam in a chain.
Definition: SlideNode.h:40
RoR::beam_t
Simulation: An edge in the softbody structure.
Definition: SimData.h:330
SlideNode.h
RoR::SlideNode::UpdatePosition
void UpdatePosition()
Checks for current rail segment and updates ideal position of the node.
Definition: SlideNode.cpp:164
SimData.h
Core data structures for simulation; Everything affected by by either physics, network or user intera...
RoR::RailSegment::rs_next
RailSegment * rs_next
Definition: SlideNode.h:48
RoR::SlideNode::GetSlideNodeId
int GetSlideNodeId()
Returns the node index of the slide node.
Definition: SlideNode.cpp:159
RoR::SlideNode::m_attach_rate
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
RoR::RailGroup::rg_segments
std::vector< RailSegment > rg_segments
Definition: SlideNode.h:60
RoR::SlideNode::getLenTo
static Ogre::Real getLenTo(const RailGroup *group, const Ogre::Vector3 &point)
Definition: SlideNode.cpp:210
RoR::node_t::pos
NodeNum_t pos
This node's index in Actor::ar_nodes array.
Definition: SimData.h:304
RoR::SlideNode::m_cur_rail_seg
RailSegment * m_cur_rail_seg
Current rail segment we are sliding on.
Definition: SlideNode.h:118
Application.h
Central state/object manager and communications hub.
RoR::node_t
Physics: A vertex in the softbody structure.
Definition: SimData.h:286
RoR::SlideNode::ResetPositions
void ResetPositions()
Recalculates the closest position on current RailGroup.
Definition: SlideNode.cpp:200
RoR::SlideNode::sn_slide_broken
bool sn_slide_broken
The slidenode was pulled away from the rail.
Definition: SlideNode.h:108
RoR::RailSegment::rs_prev
RailSegment * rs_prev
Definition: SlideNode.h:47
RoR::SlideNode::SlideNode
SlideNode(node_t *sliding_node, RailGroup *rail)
Definition: SlideNode.cpp:63
RoR::SlideNode::GetSlideNodePosition
const Ogre::Vector3 & GetSlideNodePosition() const
Definition: SlideNode.cpp:195
RoR::SlideNode::CalcCorrectiveForces
Ogre::Vector3 CalcCorrectiveForces()
Calculate forces between the ideal and actual position of the sliding node.
Definition: SlideNode.cpp:249
RoR::SlideNode::UpdateForces
void UpdateForces(float dt)
Updates the corrective forces and applies these forces to the beam.
Definition: SlideNode.cpp:87
RoR::SlideNode::m_sliding_node
node_t * m_sliding_node
Pointer to node that is sliding.
Definition: SlideNode.h:114
RoR::beam_t::p2
node_t * p2
Definition: SimData.h:336
Ogre
Definition: ExtinguishableFireAffector.cpp:35
RoR::SlideNode::m_sliding_beam
beam_t * m_sliding_beam
Pointer to current beam sliding on.
Definition: SlideNode.h:115
RoR::RailGroup::FindClosestSegment
RailSegment * FindClosestSegment(Ogre::Vector3 const &point)
Search for closest rail segment (the one with closest node in it) in the entire RailGroup.
Definition: SlideNode.cpp:114
RoR::SlideNode::m_break_force
float m_break_force
Force at which Slide Node breaks away from the rail (N)
Definition: SlideNode.h:124
RoR
Definition: AppContext.h:36
RoR::beam_t::bm_broken
bool bm_broken
Definition: SimData.h:352
RoR::node_t::Forces
Ogre::Vector3 Forces
Definition: SimData.h:296