RigsofRods
Soft-body Physics Simulation
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 "Water.h"
31 
32 using namespace Ogre;
33 using namespace RoR;
34 
35 Buoyance::Buoyance(DustPool* splash, DustPool* ripple) :
36  splashp(splash),
37  ripplep(ripple),
38  sink(0),
39  update(false)
40 {
41 }
42 
44 {
45 }
46 
47 //compute tetrahedron volume
48 inline float Buoyance::computeVolume(Vector3 o, Vector3 a, Vector3 b, Vector3 c)
49 {
50  return ((a - o).dotProduct((b - o).crossProduct(c - o))) / 6.0;
51 }
52 
53 //compute pressure and drag force on a submerged triangle
54 Vector3 Buoyance::computePressureForceSub(Vector3 a, Vector3 b, Vector3 c, Vector3 vel, int type)
55 {
56  //compute normal vector
57  Vector3 normal = (b - a).crossProduct(c - a);
58  float surf = normal.length();
59  if (surf < 0.00001)
60  return Vector3::ZERO;
61  normal = normal / surf; //normalize
62  surf = surf / 2.0; //surface
63  float vol = 0.0;
64  if (type != BUOY_DRAGONLY)
65  {
66  //compute pression prism points
67  Vector3 ap = a + (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(a) - a.y) * 9810 * normal;
68  Vector3 bp = b + (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(b) - b.y) * 9810 * normal;
69  Vector3 cp = c + (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(c) - c.y) * 9810 * normal;
70  //find centroid
71  Vector3 ctd = (a + b + c + ap + bp + cp) / 6.0;
72  //compute volume
73  vol += computeVolume(ctd, a, b, c);
74  vol += computeVolume(ctd, a, ap, bp);
75  vol += computeVolume(ctd, a, bp, b);
76  vol += computeVolume(ctd, b, bp, cp);
77  vol += computeVolume(ctd, b, cp, c);
78  vol += computeVolume(ctd, c, cp, ap);
79  vol += computeVolume(ctd, c, ap, a);
80  vol += computeVolume(ctd, ap, cp, bp);
81  };
82  Vector3 drg = Vector3::ZERO;
83  if (type != BUOY_DRAGLESS)
84  {
85  //now, the drag
86  //take in account the wave speed
87  //compute center
88  Vector3 tc = (a + b + c) / 3.0;
90  float vell = vel.length();
91  if (vell > 0.01)
92  {
93  float cosaoa = fabs(normal.dotProduct(vel / vell));
94  // drg=(-500.0*surf*vell*cosaoa)*vel;
95  drg = (-500.0 * surf * vell * vell * cosaoa) * normal;
96  if (normal.dotProduct(vel / vell) < 0)
97  drg = -drg;
98  if (update && splashp)
99  {
100  float fxl = vell * cosaoa * surf;
101  if (fxl > 1.5) //if enough pushing drag
102  {
103  Vector3 fxdir = fxl * normal;
104  if (fxdir.y < 0)
105  fxdir.y = -fxdir.y;
106 
107  if (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(a) - a.y < 0.1)
108  splashp->malloc(a, fxdir);
109 
110  else if (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(b) - b.y < 0.1)
111  splashp->malloc(b, fxdir);
112 
113  else if (App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight(c) - c.y < 0.1)
114  splashp->malloc(c, fxdir);
115  }
116  }
117  }
118  }
119  //okay
120  if (sink)
121  return drg;
122  return vol * normal + drg;
123 }
124 
125 //compute pressure and drag forces on a random triangle
126 Vector3 Buoyance::computePressureForce(Vector3 a, Vector3 b, Vector3 c, Vector3 vel, int type)
127 {
128  float wha = App::GetGameContext()->GetTerrain()->getWater()->CalcWavesHeight((a + b + c) / 3.0);
129  //check if fully emerged
130  if (a.y > wha && b.y > wha && c.y > wha)
131  return Vector3::ZERO;
132  //check if semi emerged
133  if (a.y > wha || b.y > wha || c.y > wha)
134  {
135  //okay, several cases
136  //one dip
137  if (a.y < wha && b.y > wha && c.y > wha)
138  {
139  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);
140  }
141  if (b.y < wha && c.y > wha && a.y > wha)
142  {
143  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);
144  }
145  if (c.y < wha && a.y > wha && b.y > wha)
146  {
147  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);
148  }
149  //two dips
150  if (a.y > wha && b.y < wha && c.y < wha)
151  {
152  Vector3 tb = a + (wha - a.y) / (b.y - a.y) * (b - a);
153  Vector3 tc = a + (wha - a.y) / (c.y - a.y) * (c - a);
154  Vector3 f = computePressureForceSub(tb, b, tc, vel, type);
155  return f + computePressureForceSub(tc, b, c, vel, type);
156  }
157  if (b.y > wha && c.y < wha && a.y < wha)
158  {
159  Vector3 tc = b + (wha - b.y) / (c.y - b.y) * (c - b);
160  Vector3 ta = b + (wha - b.y) / (a.y - b.y) * (a - b);
161  Vector3 f = computePressureForceSub(tc, c, ta, vel, type);
162  return f + computePressureForceSub(ta, c, a, vel, type);
163  }
164  if (c.y > wha && a.y < wha && b.y < wha)
165  {
166  Vector3 ta = c + (wha - c.y) / (a.y - c.y) * (a - c);
167  Vector3 tb = c + (wha - c.y) / (b.y - c.y) * (b - c);
168  Vector3 f = computePressureForceSub(ta, a, tb, vel, type);
169  return f + computePressureForceSub(tb, a, b, vel, type);
170  }
171  return Vector3::ZERO;
172  }
173  else
174  {
175  //fully submerged case
176  return computePressureForceSub(a, b, c, vel, type);
177  }
178 }
179 
180 void Buoyance::computeNodeForce(node_t* a, node_t* b, node_t* c, bool doUpdate, int type)
181 {
185  return;
186 
187  update = doUpdate;
188 
189  //compute center
190  Vector3 m = (a->AbsPosition + b->AbsPosition + c->AbsPosition) / 3.0;
191 
192 #if 0
193  //compute projected points
194  Vector3 tmp = b->Position - a->Position;
195  Vector3 mab = (tmp.dotProduct(m-a->Position) / tmp.squaredLength()) * tmp;
196  tmp = c->Position - b->Position;
197  Vector3 mbc = (tmp.dotProduct(m-b->Position) / tmp.squaredLength()) * tmp;
198  tmp = a->Position - c->Position;
199  Vector3 mca = (tmp.dotProduct(m-c->Position) / tmp.squaredLength()) * tmp;
200 #endif
201 
202  //suboptimal
203  Vector3 mab = (a->AbsPosition + b->AbsPosition) / 2.0;
204  Vector3 mbc = (b->AbsPosition + c->AbsPosition) / 2.0;
205  Vector3 mca = (c->AbsPosition + a->AbsPosition) / 2.0;
206  Vector3 vel = (a->Velocity + b->Velocity + c->Velocity) / 3.0;
207 
208  //apply forces
209  a->Forces += computePressureForce(a->AbsPosition, mab, m, vel, type) + computePressureForce(a->AbsPosition, m, mca, vel, type);
210  b->Forces += computePressureForce(b->AbsPosition, mbc, m, vel, type) + computePressureForce(b->AbsPosition, m, mab, vel, type);
211  c->Forces += computePressureForce(c->AbsPosition, mca, m, vel, type) + computePressureForce(c->AbsPosition, m, mbc, vel, type);
212 }
GameContext.h
Game state manager and message-queue provider.
RoR::IWater::CalcWavesHeight
virtual float CalcWavesHeight(Ogre::Vector3 pos)=0
RoR::node_t::Velocity
Ogre::Vector3 Velocity
Definition: SimData.h:294
RoR::Buoyance::computeNodeForce
void computeNodeForce(node_t *a, node_t *b, node_t *c, bool doUpdate, int type)
Definition: Buoyance.cpp:180
RoR::DustPool
Definition: DustPool.h:33
RoR::node_t::AbsPosition
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition: SimData.h:293
RoR::Buoyance::BUOY_DRAGLESS
@ BUOY_DRAGLESS
Definition: Buoyance.h:39
RoR::Buoyance::BUOY_DRAGONLY
@ BUOY_DRAGONLY
Definition: Buoyance.h:39
RoR::Buoyance::computeVolume
float computeVolume(Ogre::Vector3 o, Ogre::Vector3 a, Ogre::Vector3 b, Ogre::Vector3 c)
Definition: Buoyance.cpp:48
ActorManager.h
RoR::IWater::CalcWavesVelocity
virtual Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos)=0
SimData.h
Core data structures for simulation; Everything affected by by either physics, network or user intera...
RoR::DustPool::malloc
void malloc(Ogre::Vector3 pos, Ogre::Vector3 vel, Ogre::ColourValue col=Ogre::ColourValue(0.83, 0.71, 0.64, 1.0))
Definition: DustPool.cpp:96
GfxScene.h
RoR::Buoyance::computePressureForce
Ogre::Vector3 computePressureForce(Ogre::Vector3 a, Ogre::Vector3 b, Ogre::Vector3 c, Ogre::Vector3 vel, int type)
Definition: Buoyance.cpp:126
RoR::Buoyance::computePressureForceSub
Ogre::Vector3 computePressureForceSub(Ogre::Vector3 a, Ogre::Vector3 b, Ogre::Vector3 c, Ogre::Vector3 vel, int type)
Definition: Buoyance.cpp:54
Application.h
Central state/object manager and communications hub.
RoR::node_t
Physics: A vertex in the softbody structure.
Definition: SimData.h:285
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:280
DustPool.h
RoR::Buoyance::update
bool update
Definition: Buoyance.h:55
Buoyance.h
Terrain.h
Ogre
Definition: ExtinguishableFireAffector.cpp:35
RoR::Buoyance::splashp
DustPool * splashp
Definition: Buoyance.h:54
RoR::Buoyance::~Buoyance
~Buoyance()
Definition: Buoyance.cpp:43
RoR
Definition: AppContext.h:36
Water.h
RoR::Terrain::getWater
IWater * getWater()
Definition: Terrain.h:84
RoR::Buoyance::sink
bool sink
Definition: Buoyance.h:41
RoR::GameContext::GetTerrain
const TerrainPtr & GetTerrain()
Definition: GameContext.h:117
RoR::node_t::Forces
Ogre::Vector3 Forces
Definition: SimData.h:295