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
ProceduralManager.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 2013-2022 Petr Ohlidal
6
7 For more information, see http://www.rigsofrods.org/
8
9 Rigs of Rods is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 3, as
11 published by the Free Software Foundation.
12
13 Rigs of Rods is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "ProceduralManager.h"
23
24#include "Application.h"
25#include "ProceduralRoad.h"
26
27using namespace Ogre;
28using namespace RoR;
29
30#pragma region ProceduralObject
31
33{
34 if (pos >= 0 && pos < (int)points.size())
35 {
36 return points[pos];
37 }
38 else
39 {
40 return ProceduralPointPtr();
41 }
42}
43
45{
46 if (pos >= 0 && pos < (int)points.size())
47 {
48 points.insert(points.begin() + pos, p);
49 }
50}
51
53{
54 if (pos >= 0 && pos < (int)points.size())
55 {
56 points.erase(points.begin() + pos);
57 }
58}
59
60#pragma endregion
61
62#pragma region ProceduralManager
63
64ProceduralManager::ProceduralManager(Ogre::SceneNode* groupingSceneNode)
65 : pGroupingSceneNode(groupingSceneNode)
66{
67}
68
73
75{
76 if (pos >= 0 && pos < (int)pObjects.size())
77 {
78 return pObjects[pos];
79 }
80 else
81 {
82 return ProceduralObjectPtr();
83 }
84}
85
87{
89 {
90 this->deleteObjectMesh(obj);
91 }
92 pObjects.clear(); // delete (unreference) all objects.
93}
94
96{
97 if (po->road)
98 {
99 // loaded already, delete (unreference) old object
100 po->road = ProceduralRoadPtr();
101 }
102}
103
105{
106 for (size_t i = 0; i < pObjects.size(); i++)
107 {
108 if (pObjects[i] == po)
109 {
110 pObjects.erase(pObjects.begin() + i);
111 }
112 }
113}
114
116{
117 if (po->road)
118 this->deleteObjectMesh(po);
119
120 po->road = new ProceduralRoad();
122
123 Ogre::SimpleSpline spline;
124 if (po->smoothing_num_splits > 0)
125 {
126 // Init smoothing
127 spline.setAutoCalculate(false);
128 for (ProceduralPointPtr& pp : po->points)
129 {
130 spline.addPoint(pp->position);
131 }
132 spline.recalcTangents();
133 }
134
135 for (int i_point = 0; i_point < po->getNumPoints(); i_point++)
136 {
137 ProceduralPointPtr pp = po->getPoint(i_point);
138 if (po->smoothing_num_splits > 0)
139 {
140 const int num_segments = po->smoothing_num_splits + 1;
141
142 // smoothing on
143 for (int i_seg = 1; i_seg <= num_segments; i_seg++)
144 {
145 if (i_point == 0)
146 {
147 po->road->addBlock(pp->position, pp->rotation, pp->type, pp->width, pp->bwidth, pp->bheight, pp->pillartype);
148 }
149 else
150 {
151 const float progress = static_cast<float>(i_seg) / static_cast<float>(num_segments);
152 ProceduralPointPtr prev_pp = po->getPoint(i_point - 1);
153
154 const Ogre::Vector3 smooth_pos = spline.interpolate(i_point - 1, progress);
155 const Ogre::Quaternion smooth_rot = Quaternion::nlerp(progress, prev_pp->rotation, pp->rotation);
156 const float smooth_width = Math::lerp(prev_pp->width, pp->width, progress);
157 const float smooth_bwidth = Math::lerp(prev_pp->bwidth, pp->bwidth, progress);
158 const float smooth_bheight = Math::lerp(prev_pp->bheight, pp->bheight, progress);
159
160 po->road->addBlock(smooth_pos, smooth_rot, pp->type, smooth_width, smooth_bwidth, smooth_bheight, pp->pillartype);
161 }
162 }
163 }
164 else
165 {
166 // smoothing off
167 po->road->addBlock(pp->position, pp->rotation, pp->type, pp->width, pp->bwidth, pp->bheight, pp->pillartype);
168 }
169 }
171}
172
174{
176 pObjects.push_back(po);
177}
178
180{
181 Log("[RoR] Procedural road diagnostic.\n"
182 " types: 0=ROAD_AUTOMATIC, 1=ROAD_FLAT, 2=ROAD_LEFT, 3=ROAD_RIGHT, 4=ROAD_BOTH, 5=ROAD_BRIDGE, 6=ROAD_MONORAIL\n"
183 " pillartypes: 0=none, 1=road bridge, 2=monorail");
184 for (int i=0; i< (int) pObjects.size(); ++i)
185 {
186 LogFormat("~~~~~~ ProceduralObject %d ~~~~~~", i);
188 for (int j = 0; j<(int)po->points.size(); ++j)
189 {
190 ProceduralPointPtr& pp = po->points[j];
191 LogFormat("\t Point [%d] posXYZ %f %f %f, type %d, width %f, bwidth %f, bheight %f, pillartype %i",
192 j, pp->position.x, pp->position.y, pp->position.z,
193 pp->type, pp->width, pp->bwidth, pp->bheight, pp->pillartype);
194 }
195 }
196}
197
198#pragma endregion
quaternion Log() const
Central state/object manager and communications hub.
void rebuildObjectMesh(ProceduralObjectPtr po)
Rebuilds the road mesh.
virtual ~ProceduralManager() override
void deleteObjectMesh(ProceduralObjectPtr po)
Deletes the road mesh.
void addObject(ProceduralObjectPtr po)
Generates road mesh and adds to internal list.
ProceduralManager(Ogre::SceneNode *groupingSceneNode)
void removeObject(ProceduralObjectPtr po)
Clears road mesh and removes from internal list.
Ogre::SceneNode * pGroupingSceneNode
ProceduralObjectPtr getObject(int pos)
std::vector< ProceduralObjectPtr > pObjects
void setCollisionEnabled(bool v)
void addBlock(Ogre::Vector3 pos, Ogre::Quaternion rot, RoadType type, float width, float bwidth, float bheight, int pillartype=1)
void finish(Ogre::SceneNode *snode)
RefCountingObjectPtr< ProceduralObject > ProceduralObjectPtr
RefCountingObjectPtr< ProceduralRoad > ProceduralRoadPtr
RefCountingObjectPtr< ProceduralPoint > ProceduralPointPtr
void LogFormat(const char *format,...)
Improved logging utility. Uses fixed 2Kb buffer.
ProceduralPointPtr getPoint(int pos)
bool collision_enabled
Generate collision triangles?
std::vector< ProceduralPointPtr > points
void insertPoint(int pos, ProceduralPointPtr p)
ProceduralRoadPtr road