Rigs of Rods 2023.09
Soft-body Physics Simulation
Loading...
Searching...
No Matches
Buoyance.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
6 For more information, see http://www.rigsofrods.org/
7
8 Rigs of Rods is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 3, as
10 published by the Free Software Foundation.
11
12 Rigs of Rods is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "Buoyance.h"
22
23#include "Application.h"
24#include "SimData.h"
25#include "ActorManager.h"
26#include "GameContext.h"
27#include "GfxScene.h"
28#include "DustPool.h"
29#include "Terrain.h"
30#include "GfxWater.h"
31
32using namespace Ogre;
33using namespace RoR;
34
36 splashp(splash),
37 ripplep(ripple)
38{
39}
40
44
46{
47 auto itor = std::find_if(buoy_cached_nodes.begin(), buoy_cached_nodes.end(),
48 [n](BuoyCachedNode& bcn)
49 {
50 return bcn.nodenum == n->pos;
51 });
52
53 if (itor == buoy_cached_nodes.end())
54 {
55 BuoyCachedNodeID_t retval = static_cast<BuoyCachedNodeID_t>(buoy_cached_nodes.size());
56 buoy_cached_nodes.emplace_back(n->pos);
57 return retval;
58 }
59
60 return static_cast<BuoyCachedNodeID_t>(std::distance(buoy_cached_nodes.begin(), itor));
61}
62
63//compute tetrahedron volume
64inline float Buoyance::computeVolume(Vec3 o, Vec3 a, Vec3 b, Vec3 c)
65{
66 return ((a - o).dotProduct((b - o).crossProduct(c - o))) / 6.0;
67}
68
69//compute pressure and drag force on a submerged triangle
71{
72 //compute normal vector
73 Vec3 normal = (b - a).crossProduct(c - a);
74 float surf = normal.length();
75 if (surf < 0.00001)
76 return Vec3();
77 normal = normal / surf; //normalize
78 surf = surf / 2.0; //surface
79 float vol = 0.0;
80 if (type != BUOY_DRAGONLY)
81 {
82 //compute pression prism points
83 Vec3 ap = a + (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(a) - a.y) * 9810 * normal;
84 Vec3 bp = b + (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(b) - b.y) * 9810 * normal;
85 Vec3 cp = c + (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(c) - c.y) * 9810 * normal;
86 //find centroid
87 Vec3 ctd = (a + b + c + ap + bp + cp) / 6.0;
88 //compute volume
89 vol += computeVolume(ctd, a, b, c);
90 vol += computeVolume(ctd, a, ap, bp);
91 vol += computeVolume(ctd, a, bp, b);
92 vol += computeVolume(ctd, b, bp, cp);
93 vol += computeVolume(ctd, b, cp, c);
94 vol += computeVolume(ctd, c, cp, ap);
95 vol += computeVolume(ctd, c, ap, a);
96 vol += computeVolume(ctd, ap, cp, bp);
97 };
98 Vec3 drg;
99 if (type != BUOY_DRAGLESS)
100 {
101 //now, the drag
102 //take in account the wave speed
103 //compute center
104 Vec3 tc = (a + b + c) / 3.0;
106 float vell = vel.length();
107 if (vell > 0.01)
108 {
109 float cosaoa = fabs(normal.dotProduct(vel / vell));
110 // drg=(-500.0*surf*vell*cosaoa)*vel;
111 drg = (-500.0 * surf * vell * vell * cosaoa) * normal;
112 if (normal.dotProduct(vel / vell) < 0)
113 drg = -drg;
114 if (update && splashp)
115 {
116 float fxl = vell * cosaoa * surf;
117 if (fxl > 1.5) //if enough pushing drag
118 {
119 Vec3 fxdir = fxl * normal;
120 if (fxdir.y < 0)
121 fxdir.y = -fxdir.y;
122
123 if (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(a) - a.y < 0.1)
124 splashp->malloc(a, fxdir);
125
126 else if (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(b) - b.y < 0.1)
127 splashp->malloc(b, fxdir);
128
129 else if (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(c) - c.y < 0.1)
130 splashp->malloc(c, fxdir);
131 }
132 }
133 }
134 }
135 //okay
136 if (sink)
137 return drg;
138 if (update && buoy_debug_view)
139 {
140 buoy_debug_subcabs.emplace_back(a, b, c, normal, drg, vol);
141 }
142 return vol * normal + drg;
143}
144
145//compute pressure and drag forces on a random triangle
147{
148 float wha = App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight((a + b + c) / 3.0);
149 //check if fully emerged
150 if (a.y > wha && b.y > wha && c.y > wha)
151 return Vec3();
152 //check if semi emerged
153 if (a.y > wha || b.y > wha || c.y > wha)
154 {
155 //okay, several cases
156 //one dip
157 if (a.y < wha && b.y > wha && c.y > wha)
158 {
159 return computePressureForceSub(a, a + (wha - a.y) / (b.y - a.y) * (b - a), a + (wha - a.y) / (c.y - a.y) * (c - a), vel, type);
160 }
161 if (b.y < wha && c.y > wha && a.y > wha)
162 {
163 return computePressureForceSub(b, b + (wha - b.y) / (c.y - b.y) * (c - b), b + (wha - b.y) / (a.y - b.y) * (a - b), vel, type);
164 }
165 if (c.y < wha && a.y > wha && b.y > wha)
166 {
167 return computePressureForceSub(c, c + (wha - c.y) / (a.y - c.y) * (a - c), c + (wha - c.y) / (b.y - c.y) * (b - c), vel, type);
168 }
169 //two dips
170 if (a.y > wha && b.y < wha && c.y < wha)
171 {
172 Vec3 tb = a + (wha - a.y) / (b.y - a.y) * (b - a);
173 Vec3 tc = a + (wha - a.y) / (c.y - a.y) * (c - a);
174 Vec3 f = computePressureForceSub(tb, b, tc, vel, type);
175 return f + computePressureForceSub(tc, b, c, vel, type);
176 }
177 if (b.y > wha && c.y < wha && a.y < wha)
178 {
179 Vec3 tc = b + (wha - b.y) / (c.y - b.y) * (c - b);
180 Vec3 ta = b + (wha - b.y) / (a.y - b.y) * (a - b);
181 Vec3 f = computePressureForceSub(tc, c, ta, vel, type);
182 return f + computePressureForceSub(ta, c, a, vel, type);
183 }
184 if (c.y > wha && a.y < wha && b.y < wha)
185 {
186 Vec3 ta = c + (wha - c.y) / (a.y - c.y) * (a - c);
187 Vec3 tb = c + (wha - c.y) / (b.y - c.y) * (b - c);
188 Vec3 f = computePressureForceSub(ta, a, tb, vel, type);
189 return f + computePressureForceSub(tb, a, b, vel, type);
190 }
191 return Vec3();
192 }
193 else
194 {
195 //fully submerged case
196 return computePressureForceSub(a, b, c, vel, type);
197 }
198}
199
201{
205 return;
206
207 //compute center
208 Vec3 m = (a->AbsPosition + b->AbsPosition + c->AbsPosition) / 3.0;
209
210 //suboptimal
211 Vec3 mab = (a->AbsPosition + b->AbsPosition) / 2.0;
212 Vec3 mbc = (b->AbsPosition + c->AbsPosition) / 2.0;
213 Vec3 mca = (c->AbsPosition + a->AbsPosition) / 2.0;
214 Vec3 vel = (a->Velocity + b->Velocity + c->Velocity) / 3.0;
215
216 //apply forces
217 a->Forces += computePressureForce(a->AbsPosition, mab, m, vel, type) + computePressureForce(a->AbsPosition, m, mca, vel, type);
218 b->Forces += computePressureForce(b->AbsPosition, mbc, m, vel, type) + computePressureForce(b->AbsPosition, m, mab, vel, type);
219 c->Forces += computePressureForce(c->AbsPosition, mca, m, vel, type) + computePressureForce(c->AbsPosition, m, mbc, vel, type);
220}
Central state/object manager and communications hub.
Game state manager and message-queue provider.
Core data structures for simulation; Everything affected by by either physics, network or user intera...
DustPool * splashp
Definition Buoyance.h:90
std::vector< BuoyDebugSubCab > buoy_debug_subcabs
Definition Buoyance.h:75
std::vector< BuoyCachedNode > buoy_cached_nodes
Definition Buoyance.h:71
BuoyCachedNodeID_t cacheBuoycabNode(node_t *n)
try adding the node to internal list (each node is only listed once).
Definition Buoyance.cpp:45
bool buoy_debug_view
Definition Buoyance.h:74
Buoyance(DustPool *splash, DustPool *ripple)
Definition Buoyance.cpp:35
Vec3 computePressureForce(Vec3 a, Vec3 b, Vec3 c, Vec3 vel, int type)
Definition Buoyance.cpp:146
Vec3 computePressureForceSub(Vec3 a, Vec3 b, Vec3 c, Vec3 vel, int type)
Definition Buoyance.cpp:70
void computeNodeForce(BuoyCachedNode *a, BuoyCachedNode *b, BuoyCachedNode *c, int type, float timeshift)
Definition Buoyance.cpp:200
float computeVolume(Vec3 o, Vec3 a, Vec3 b, Vec3 c)
Definition Buoyance.cpp:64
void malloc(Ogre::Vector3 pos, Ogre::Vector3 vel, Ogre::ColourValue col=Ogre::ColourValue(0.83, 0.71, 0.64, 1.0))
Definition DustPool.cpp:97
const TerrainPtr & GetTerrain()
Wavefield * getWater()
Definition Terrain.h:87
Vec3 CalcWavesVelocity(Vec3 pos, float timeshift_sec=0.f)
float CalcWavesHeight(Vec3 pos, float timeshift_sec=0.f)
Definition Wavefield.cpp:90
GameContext * GetGameContext()
int BuoyCachedNodeID_t
Designed to work smoothly with optimizations disabled.
Definition Vec3.h:29
float dotProduct(const Vec3 &b) const
Definition Vec3.h:50
float y
Definition Vec3.h:30
float length() const
Definition Vec3.h:52
Physics: A vertex in the softbody structure.
Definition SimData.h:260
NodeNum_t pos
This node's index in Actor::ar_nodes array.
Definition SimData.h:277