RigsofRods
Soft-body Physics Simulation
TorqueCurve.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 "TorqueCurve.h"
22 
23 #include "Application.h"
24 #include "Utils.h"
25 
26 #include <Ogre.h>
27 
28 using namespace Ogre;
29 using namespace RoR;
30 
31 const String TorqueCurve::customModel = "CustomModel";
32 
33 TorqueCurve::TorqueCurve() : usedSpline(0), usedModel("")
34 {
36  setTorqueModel("default");
37 }
38 
40 {
41  splines.clear();
42 }
43 
45 {
46  if (!usedSpline)
47  return 0.0f;
48  if (usedSpline->getNumPoints() == 1)
49  return usedSpline->getPoint(0).y;
50  float minRPM = usedSpline->getPoint(0).x;
51  float maxRPM = usedSpline->getPoint(usedSpline->getNumPoints() - 1).x;
52  if (minRPM == maxRPM)
53  return usedSpline->getPoint(0).y;
54  float t = Math::Clamp((rpm - minRPM) / (maxRPM - minRPM), 0.0f, 1.0f);
55  return usedSpline->interpolate(t).y;
56 }
57 
59 {
60  //LOG("loading default torque Curves");
61  // check if we have a config file
62  String group = "";
63  try
64  {
65  group = ResourceGroupManager::getSingleton().findGroupContainingResource("torque_models.cfg");
66  }
67  catch (...)
68  {
69  }
70  // emit a warning if we did not found the file
71  if (group.empty())
72  {
73  LOG("torque_models.cfg not found");
74  return 1;
75  }
76 
77  // open the file for reading
78  DataStreamPtr ds = ResourceGroupManager::getSingleton().openResource("torque_models.cfg", group);
79  String line = "";
80  String currentModel = "";
81 
82  while (!ds->eof())
83  {
84  line = SanitizeUtf8String(ds->getLine());
85  StringUtil::trim(line);
86 
87  if (line.empty() || line[0] == ';')
88  continue;
89 
90  Ogre::StringVector args = StringUtil::split(line, ",");
91 
92  if (args.size() == 1)
93  {
94  currentModel = line;
95  continue;
96  }
97 
98  // process the line if we got a model
99  if (!currentModel.empty())
100  processLine(args, currentModel);
101  }
102  return 0;
103 }
104 
105 int TorqueCurve::processLine(Ogre::StringVector args, String model)
106 {
107  // if its just one arguments, it must be a known model
108  if (args.size() == 1)
109  return setTorqueModel(args[0]);
110 
111  // we only accept 2 arguments
112  if (args.size() != 2)
113  return 1;
114  // parse the data
115  float pointx = StringConverter::parseReal(args[0]);
116  float pointy = StringConverter::parseReal(args[1]);
117  Vector3 point = Vector3(pointx, pointy, 0);
118 
119  // find the spline to attach the points
120  if (splines.find(model) == splines.end())
121  splines[model] = SimpleSpline();
122 
123  // attach the points to the spline
124  // LOG("curve "+model+" : " + TOSTRING(point));
125  splines[model].addPoint(point);
126 
127  // special case for custom model:
128  // we set it as active curve as well!
129  if (model == TorqueCurve::customModel)
131 
132  return 0;
133 }
134 
135 bool TorqueCurve::CreateNewCurve(Ogre::String const& name)
136 {
137  if (splines.find(name) != splines.end())
138  {
139  return false;
140  }
141  splines[name] = Ogre::SimpleSpline();
142 
143  /* special case for custom model: we set it as active curve as well! */
144  if (name == TorqueCurve::customModel)
145  {
147  }
148  return true;
149 }
150 
151 void TorqueCurve::AddCurveSample(float rpm, float progress, Ogre::String const& model)
152 {
153  /* attach the points to the spline */
154  splines[model].addPoint(Ogre::Vector3(rpm, progress, 0));
155 }
156 
158 {
159  //LOG("using torque curve: " + name);
160  // check if we have such a model loaded
161  if (splines.find(name) == splines.end())
162  {
163  LOG("Torquemodel "+String(name)+" not found! ignoring that and using default model...");
164  return 1;
165  }
166  // use the model
167  usedSpline = &splines.find(name)->second;
168  usedModel = name;
169  return 0;
170 }
171 
172 int TorqueCurve::spaceCurveEvenly(Ogre::SimpleSpline* spline)
173 {
174  if (!spline)
175  return 2;
176 
177  SimpleSpline tmpSpline = *spline;
178  Real points = tmpSpline.getNumPoints();
179 
180  if (points > 1)
181  {
182  // clear the original spline, so it's prepared for the new corrected numbers
183  spline->clear();
184  Real minDistance = tmpSpline.getPoint(1).x - tmpSpline.getPoint(0).x;
185  // looking for the minimum distance (spacing) in the current spline
186  for (int i = 2; i < points; i++)
187  {
188  Real distance = tmpSpline.getPoint(i).x - tmpSpline.getPoint(i - 1).x;
189  minDistance = std::min(distance, minDistance);
190  }
191  // the rpm points must be in an ascending order, as the points should be added at the end of the spline
192  if (minDistance < 0)
193  return 1;
194  // first(smallest)- and last(greatest) rpm
195  Vector3 minPoint = tmpSpline.getPoint(0);
196  Vector3 maxPoint = tmpSpline.getPoint(points - 1);
197 
198  Real rpmPoint = minPoint.x;
199  int pointIndex = 1; // this is the index used to interpolate between the rpm points
200  while (rpmPoint <= maxPoint.x && pointIndex < points)
201  {
202  // if actual rpm is higher than point of the spline, proceed to the next point
203  if (rpmPoint > tmpSpline.getPoint(pointIndex).x)
204  pointIndex++;
205  // interpolate(linear)
206  Real newPoint = tmpSpline.getPoint(pointIndex - 1).y + (tmpSpline.getPoint(pointIndex).y - tmpSpline.getPoint(pointIndex - 1).y) /
207  (tmpSpline.getPoint(pointIndex).x - tmpSpline.getPoint(pointIndex - 1).x) * (rpmPoint - tmpSpline.getPoint(pointIndex - 1).x);
208  spline->addPoint(Vector3(rpmPoint, newPoint, 0));
209  rpmPoint += minDistance;
210  }
211  // if the last point is missing due the even spacing, we add the last point manually
212  // criterion is that it must be smaller than 1% of the maximum rpm.
213  if (spline->getPoint(spline->getNumPoints() - 1).x < maxPoint.x && (rpmPoint - maxPoint.x) < 0.01 * maxPoint.x)
214  {
215  spline->addPoint(Vector3(rpmPoint, maxPoint.y, 0));
216  }
217  }
218 
219  return 0;
220 }
RoR::TorqueCurve::loadDefaultTorqueModels
int loadDefaultTorqueModels()
Loads default torque models from the 'torque_models.cfg' file.
Definition: TorqueCurve.cpp:58
RoR::TorqueCurve::spaceCurveEvenly
int spaceCurveEvenly(Ogre::SimpleSpline *spline)
Spaces the points of a spline evenly; this is needed for the correct calculation of the Ogre simple s...
Definition: TorqueCurve.cpp:172
RoR::SanitizeUtf8String
std::string SanitizeUtf8String(std::string const &str_in)
Definition: Utils.cpp:117
RoR::TorqueCurve::AddCurveSample
void AddCurveSample(float rpm, float progress, Ogre::String const &model=customModel)
Adds a point to the torque curve graph.
Definition: TorqueCurve.cpp:151
RoR::TorqueCurve::usedModel
Ogre::String usedModel
name of the torque model used by the truck.
Definition: TorqueCurve.h:114
Utils.h
RoR::TorqueCurve::usedSpline
Ogre::SimpleSpline * usedSpline
spline which is used for calculating the torque, set by setTorqueModel().
Definition: TorqueCurve.h:113
RoR::TorqueCurve::customModel
const static Ogre::String customModel
Definition: TorqueCurve.h:45
RoR::TorqueCurve::~TorqueCurve
~TorqueCurve()
Destructor.
Definition: TorqueCurve.cpp:39
RoR::TorqueCurve::setTorqueModel
int setTorqueModel(Ogre::String name)
Sets the torque model which is used for the vehicle.
Definition: TorqueCurve.cpp:157
TorqueCurve.h
torquecurve loader.
RoR::TorqueCurve::processLine
int processLine(Ogre::StringVector args, Ogre::String model)
Processes the given vector.
Definition: TorqueCurve.cpp:105
Application.h
Central state/object manager and communications hub.
RoR::TorqueCurve::CreateNewCurve
bool CreateNewCurve(Ogre::String const &name=customModel)
Creates new torque curve.
Definition: TorqueCurve.cpp:135
RoR::TorqueCurve::getEngineTorque
Ogre::Real getEngineTorque(Ogre::Real rpm)
Returns the calculated engine torque based on the given RPM, interpolating the torque curve spline.
Definition: TorqueCurve.cpp:44
Ogre
Definition: ExtinguishableFireAffector.cpp:35
RoR::TorqueCurve::splines
std::map< Ogre::String, Ogre::SimpleSpline > splines
container were all torque curve splines are stored in.
Definition: TorqueCurve.h:115
RoR
Definition: AppContext.h:36