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
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
28using namespace Ogre;
29using namespace RoR;
30
31const String TorqueCurve::customModel = "CustomModel";
32
33TorqueCurve::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
105int 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
135bool 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
151void 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
172int 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}
Central state/object manager and communications hub.
void LOG(const char *msg)
Legacy alias - formerly a macro.
torquecurve loader.
Ogre::String usedModel
name of the torque model used by the truck.
void AddCurveSample(float rpm, float progress, Ogre::String const &model=customModel)
Adds a point to the torque curve graph.
TorqueCurve()
Constructor.
int loadDefaultTorqueModels()
Loads default torque models from the 'torque_models.cfg' file.
static const Ogre::String customModel
Definition TorqueCurve.h:45
int spaceCurveEvenly(Ogre::SimpleSpline *spline)
Spaces the points of a spline evenly; this is needed for the correct calculation of the Ogre simple s...
int processLine(Ogre::StringVector args, Ogre::String model)
Processes the given vector.
Ogre::SimpleSpline * usedSpline
spline which is used for calculating the torque, set by setTorqueModel().
int setTorqueModel(Ogre::String name)
Sets the torque model which is used for the vehicle.
Ogre::Real getEngineTorque(Ogre::Real rpm)
Returns the calculated engine torque based on the given RPM, interpolating the torque curve spline.
std::map< Ogre::String, Ogre::SimpleSpline > splines
container were all torque curve splines are stored in.
bool CreateNewCurve(Ogre::String const &name=customModel)
Creates new torque curve.
~TorqueCurve()
Destructor.
std::string SanitizeUtf8String(std::string const &str_in)
Definition Utils.cpp:120