RigsofRods
Soft-body Physics Simulation
ProceduralRoad.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 "ProceduralRoad.h"
22 
23 #include "Actor.h"
24 #include "Application.h"
25 #include "Collisions.h"
26 #include "Console.h"
27 #include "GameContext.h"
28 #include "GfxScene.h"
29 #include "Terrain.h"
30 
31 #include <Ogre.h>
32 
33 using namespace Ogre;
34 using namespace RoR;
35 
36 static int id_counter = 0;
37 
38 ProceduralRoad::ProceduralRoad()
39 {
40  mid = id_counter++;
41 }
42 
43 ProceduralRoad::~ProceduralRoad()
44 {
45  if (snode)
46  {
47  App::GetGfxScene()->GetSceneManager()->destroySceneNode(snode);
48  snode = nullptr;
49  }
50  if (!msh.isNull())
51  {
52  MeshManager::getSingleton().remove(msh->getName());
53  msh.setNull();
54  }
55  for (int number : registeredCollTris)
56  {
58  }
59 }
60 
61 void ProceduralRoad::finish(Ogre::SceneNode* snode)
62 {
63  Vector3 pts[8];
64  computePoints(pts, lastpos, lastrot, lasttype, lastwidth, lastbwidth, lastbheight);
65  addQuad(pts[7], pts[6], pts[5], pts[4], TextureFit::TEXFIT_NONE, lastpos, lastpos, lastwidth);
66  addQuad(pts[7], pts[4], pts[3], pts[0], TextureFit::TEXFIT_NONE, lastpos, lastpos, lastwidth);
67  addQuad(pts[3], pts[2], pts[1], pts[0], TextureFit::TEXFIT_NONE, lastpos, lastpos, lastwidth);
68 
69  createMesh();
70  String entity_name = String("RoadSystem_Instance-").append(StringConverter::toString(mid));
71  String mesh_name = String("RoadSystem-").append(StringConverter::toString(mid));
72  Entity* ec = App::GetGfxScene()->GetSceneManager()->createEntity(entity_name, mesh_name);
73  snode->attachObject(ec);
74 
76  "RoadSystem", mesh_name,
77  ec->getBoundingBox().getCenter(), ec->getMesh()->getBounds(),
78  /*groundmodel:*/nullptr, registeredCollTris[0], (int)registeredCollTris.size());
79 }
80 
81 void ProceduralRoad::addBlock(Vector3 pos, Quaternion rot, RoadType type, float width, float bwidth, float bheight, int pillartype)
82 {
83  if (type == RoadType::ROAD_AUTOMATIC)
84  {
85  width = 10.0;
86  bwidth = 1.4;
87  bheight = 0.2;
88  //define type
89  Vector3 leftv = pos + rot * Vector3(0, 0, bwidth + width / 2.0);
90  Vector3 rightv = pos + rot * Vector3(0, 0, -bwidth - width / 2.0);
91  float dleft = leftv.y - RoR::App::GetGameContext()->GetTerrain()->GetHeightAt(leftv.x, leftv.z);
92  float dright = rightv.y - RoR::App::GetGameContext()->GetTerrain()->GetHeightAt(rightv.x, rightv.z);
93  if (dleft < bheight + 0.1 && dright < bheight + 0.1)
94  type = RoadType::ROAD_FLAT;
95  if (dleft < bheight + 0.1 && dright >= bheight + 0.1 && dright < 4.0)
96  type = RoadType::ROAD_LEFT;
97  if (dleft >= bheight + 0.1 && dleft < 4.0 && dright < bheight + 0.1)
98  type = RoadType::ROAD_RIGHT;
99  if (dleft >= bheight + 0.1 && dleft < 4.0 && dright >= bheight + 0.1 && dright < 4.0)
100  type = RoadType::ROAD_BOTH;
101  if (type == RoadType::ROAD_AUTOMATIC)
102  type = RoadType::ROAD_BRIDGE;
103  if (type != RoadType::ROAD_FLAT)
104  {
105  width = 10.0;
106  bwidth = 0.4;
107  bheight = 0.5;
108  };
109  }
110 
111  Vector3 pts[8];
112  if (!first)
113  {
114  Vector3 lpts[8];
115  if (type == RoadType::ROAD_MONORAIL)
116  pos.y += 2;
117 
118  computePoints(pts, pos, rot, type, width, bwidth, bheight);
119  computePoints(lpts, lastpos, lastrot, lasttype, lastwidth, lastbwidth, lastbheight);
120 
121  //tarmac
122  if (type == RoadType::ROAD_MONORAIL)
123  addQuad(pts[4], lpts[4], lpts[3], pts[3], TextureFit::TEXFIT_CONCRETETOP, pos, lastpos, width);
124  else
125  addQuad(pts[4], lpts[4], lpts[3], pts[3], TextureFit::TEXFIT_ROAD, pos, lastpos, width);
126 
127  if (type == RoadType::ROAD_FLAT && lasttype == RoadType::ROAD_FLAT)
128  {
129  //sides (close)
130  addQuad(pts[5], lpts[5], lpts[4], pts[4], TextureFit::TEXFIT_ROADS3, pos, lastpos, width);
131  addQuad(pts[3], lpts[3], lpts[2], pts[2], TextureFit::TEXFIT_ROADS2, pos, lastpos, width);
132  //sides (far)
133  addQuad(pts[6], lpts[6], lpts[5], pts[5], TextureFit::TEXFIT_ROADS4, pos, lastpos, width);
134  addQuad(pts[2], lpts[2], lpts[1], pts[1], TextureFit::TEXFIT_ROADS1, pos, lastpos, width);
135  }
136  else
137  {
138  //sides (close)
139  addQuad(pts[5], lpts[5], lpts[4], pts[4], TextureFit::TEXFIT_CONCRETEWALLI, pos, lastpos, width, (type == RoadType::ROAD_FLAT || type == RoadType::ROAD_LEFT));
140  addQuad(pts[3], lpts[3], lpts[2], pts[2], TextureFit::TEXFIT_CONCRETEWALLI, pos, lastpos, width, !(type == RoadType::ROAD_FLAT || type == RoadType::ROAD_RIGHT));
141  //sides (far)
142  addQuad(pts[6], lpts[6], lpts[5], pts[5], TextureFit::TEXFIT_CONCRETETOP, pos, lastpos, width, (type == RoadType::ROAD_FLAT || type == RoadType::ROAD_LEFT));
143  addQuad(pts[2], lpts[2], lpts[1], pts[1], TextureFit::TEXFIT_CONCRETETOP, pos, lastpos, width, !(type == RoadType::ROAD_FLAT || type == RoadType::ROAD_RIGHT));
144  }
145  if (type == RoadType::ROAD_BRIDGE || lasttype == RoadType::ROAD_BRIDGE || type == RoadType::ROAD_MONORAIL || lasttype == RoadType::ROAD_MONORAIL)
146  {
147  //walls
148  addQuad(pts[1], lpts[1], lpts[0], pts[0], TextureFit::TEXFIT_CONCRETEWALL, pos, lastpos, width);
149  addQuad(lpts[6], pts[6], pts[7], lpts[7], TextureFit::TEXFIT_CONCRETEWALL, pos, lastpos, width);
150  //underside - we flip the underside so it folds gracefully with the top
151  addQuad(pts[0], lpts[0], lpts[7], pts[7], TextureFit::TEXFIT_CONCRETEUNDER, pos, lastpos, width, true);
152  }
153  else
154  {
155  //walls
156  addQuad(pts[1], lpts[1], lpts[0], pts[0], TextureFit::TEXFIT_BRICKWALL, pos, lastpos, width);
157  addQuad(lpts[6], pts[6], pts[7], lpts[7], TextureFit::TEXFIT_BRICKWALL, pos, lastpos, width);
158  }
159  if ((type == RoadType::ROAD_BRIDGE || type == RoadType::ROAD_MONORAIL) && pillartype > 0)
160  {
161  /* this is the basic bridge pillar mod.
162  * it will create on pillar for each segment!
163  * @todo: create only a few pillars instead of so much!
164  */
165  // construct the pillars
166  Vector3 leftv = pos + rot * Vector3(0, 0, bwidth + width / 2.0);
167  Vector3 rightv = pos + rot * Vector3(0, 0, -bwidth - width / 2.0);
168  Vector3 middle = lpts[0] - ((lpts[0] + (pts[1] - lpts[0]) / 2) -
169  (lpts[7] + (pts[6] - lpts[7]) / 2)) * 0.5;
170  float heightleft = RoR::App::GetGameContext()->GetTerrain()->GetHeightAt(leftv.x, leftv.z);
171  float heightright = RoR::App::GetGameContext()->GetTerrain()->GetHeightAt(rightv.x, rightv.z);
172  float heightmiddle = RoR::App::GetGameContext()->GetTerrain()->GetHeightAt(middle.x, middle.z);
173 
174  bool builtpillars = true;
175 
176  float sidefactor = 0.5; // 0.5 = middle
177  // only re-position short pillars! (< 10 meters)
178  // so big bridge pillars do not get repositioned
179  if (pos.y - heightmiddle < 10)
180  {
181  if (heightleft >= heightright)
182  sidefactor = 0.8;
183  else
184  sidefactor = 0.2;
185  }
186 
187  static int pillarcounter = 0;
188  pillarcounter++;
189 
190  if (pillartype == 2)
191  {
192  // always in the middle
193  sidefactor = 0.5;
194  // only build every fifth pillar
195  if (pillarcounter % 5)
196  builtpillars = false;
197  }
198 
199  middle = lpts[0] - ((lpts[0] + (pts[1] - lpts[0]) / 2) -
200  (lpts[7] + (pts[6] - lpts[7]) / 2)) * sidefactor;
201  float len = middle.y - RoR::App::GetGameContext()->GetTerrain()->GetHeightAt(middle.x, middle.z) + 5;
202  float width2 = len / 30;
203 
204  if (pillartype == 2 && len > 20)
205  // no over-long pillars
206  builtpillars = false;
207 
208  // do not draw too small pillars, the bridge may hold without them ;)
209  if (width2 > 5)
210  width2 = 5;
211 
212  if (pillartype == 2)
213  width2 = 0.2;
214 
215  if (width2 >= 0.2 && builtpillars)
216  {
217  //sides
218  addQuad(middle + Vector3(-width2, -len, -width2),
219  middle + Vector3(-width2, 0, -width2),
220  middle + Vector3(width2, 0, -width2),
221  middle + Vector3(width2, -len, -width2),
222  TextureFit::TEXFIT_CONCRETETOP, pos, lastpos, width2);
223 
224  addQuad(middle + Vector3(width2, -len, width2),
225  middle + Vector3(width2, 0, width2),
226  middle + Vector3(-width2, 0, width2),
227  middle + Vector3(-width2, -len, width2),
228  TextureFit::TEXFIT_CONCRETETOP, pos, lastpos, width2);
229 
230  addQuad(middle + Vector3(-width2, -len, width2),
231  middle + Vector3(-width2, 0, width2),
232  middle + Vector3(-width2, 0, -width2),
233  middle + Vector3(-width2, -len, -width2),
234  TextureFit::TEXFIT_CONCRETETOP, pos, lastpos, width2);
235 
236  addQuad(middle + Vector3(width2, -len, -width2),
237  middle + Vector3(width2, 0, -width2),
238  middle + Vector3(width2, 0, width2),
239  middle + Vector3(width2, -len, width2),
240  TextureFit::TEXFIT_CONCRETETOP, pos, lastpos, width2);
241  }
242  }
243  }
244  else
245  {
246  first = false;
247  computePoints(pts, pos, rot, type, width, bwidth, bheight);
248  addQuad(pts[0], pts[1], pts[2], pts[3], TextureFit::TEXFIT_NONE, pos, pos, width);
249  addQuad(pts[0], pts[3], pts[4], pts[7], TextureFit::TEXFIT_NONE, pos, pos, width);
250  addQuad(pts[4], pts[5], pts[6], pts[7], TextureFit::TEXFIT_NONE, pos, pos, width);
251  }
252  lastpos = pos;
253  lastrot = rot;
254  lastwidth = width;
255  lastbwidth = bwidth;
256  lastbheight = bheight;
257  lasttype = type;
258 
259  if (App::diag_terrn_log_roads->getBool())
260  {
261  Str<2000> msg; msg << "[RoR] Road Block |";
262  msg << " pos=(" << pos.x << " " << pos.y << " " << pos.z << ")";
263  msg << " rot=(" << rot.x << " " << rot.y << " " << rot.z << ")";
264  msg << " width=" << width;
265  msg << " bwidth=" << bwidth;
266  msg << " bheight=" << bheight;
267  msg << " type=" << (int)type;
268  for (int i = 0; i < 8; ++i)
269  {
270  msg << "\n\t Point#" << i << ": " << pts[i].x << " " << pts[i].y << " " << pts[i].z;
271  }
272  Log(msg.ToCStr());
273  }
274 }
275 
276 void ProceduralRoad::computePoints(Vector3* pts, Vector3 pos, Quaternion rot, RoadType type, float width, float bwidth, float bheight)
277 {
278  if (type == RoadType::ROAD_FLAT)
279  {
280  pts[1] = pos + rot * Vector3(0, -bheight, bwidth + width / 2.0);
281  pts[0] = baseOf(pts[1]);
282  pts[2] = pos + rot * Vector3(0, -bheight / 4.0, bwidth / 3.0 + width / 2.0);
283  pts[3] = pos + rot * Vector3(0, 0, width / 2.0);
284  pts[4] = pos + rot * Vector3(0, 0, -width / 2.0);
285  pts[5] = pos + rot * Vector3(0, -bheight / 4.0, -bwidth / 3.0 - width / 2.0);
286  pts[6] = pos + rot * Vector3(0, -bheight, -bwidth - width / 2.0);
287  pts[7] = baseOf(pts[6]);
288  }
289  if (type == RoadType::ROAD_BOTH)
290  {
291  pts[1] = pos + rot * Vector3(0, bheight, bwidth + width / 2.0);
292  pts[0] = baseOf(pts[1]);
293  pts[2] = pos + rot * Vector3(0, bheight, width / 2.0);
294  pts[3] = pos + rot * Vector3(0, 0, width / 2.0);
295  pts[4] = pos + rot * Vector3(0, 0, -width / 2.0);
296  pts[5] = pos + rot * Vector3(0, bheight, -width / 2.0);
297  pts[6] = pos + rot * Vector3(0, bheight, -bwidth - width / 2.0);
298  pts[7] = baseOf(pts[6]);
299  }
300  if (type == RoadType::ROAD_LEFT)
301  {
302  pts[1] = pos + rot * Vector3(0, -bheight, bwidth + width / 2.0);
303  pts[0] = baseOf(pts[1]);
304  pts[2] = pos + rot * Vector3(0, -bheight / 4.0, bwidth / 3.0 + width / 2.0);
305  pts[3] = pos + rot * Vector3(0, 0, width / 2.0);
306  pts[4] = pos + rot * Vector3(0, 0, -width / 2.0);
307  pts[5] = pos + rot * Vector3(0, bheight, -width / 2.0);
308  pts[6] = pos + rot * Vector3(0, bheight, -bwidth - width / 2.0);
309  pts[7] = baseOf(pts[6]);
310  }
311  if (type == RoadType::ROAD_RIGHT)
312  {
313  pts[1] = pos + rot * Vector3(0, bheight, bwidth + width / 2.0);
314  pts[0] = baseOf(pts[1]);
315  pts[2] = pos + rot * Vector3(0, bheight, width / 2.0);
316  pts[3] = pos + rot * Vector3(0, 0, width / 2.0);
317  pts[4] = pos + rot * Vector3(0, 0, -width / 2.0);
318  pts[5] = pos + rot * Vector3(0, -bheight / 4.0, -bwidth / 3.0 - width / 2.0);
319  pts[6] = pos + rot * Vector3(0, -bheight, -bwidth - width / 2.0);
320  pts[7] = baseOf(pts[6]);
321  }
322  if (type == RoadType::ROAD_BRIDGE)
323  {
324  pts[0] = pos + rot * Vector3(0, -0.4, bwidth + width / 2.0);
325  pts[1] = pos + rot * Vector3(0, bheight, bwidth + width / 2.0);
326  pts[2] = pos + rot * Vector3(0, bheight, width / 2.0);
327  pts[3] = pos + rot * Vector3(0, 0, width / 2.0);
328  pts[4] = pos + rot * Vector3(0, 0, -width / 2.0);
329  pts[5] = pos + rot * Vector3(0, bheight, -width / 2.0);
330  pts[6] = pos + rot * Vector3(0, bheight, -bwidth - width / 2.0);
331  pts[7] = pos + rot * Vector3(0, -0.4, -bwidth - width / 2.0);
332  }
333  if (type == RoadType::ROAD_MONORAIL)
334  {
335  pts[0] = pos + rot * Vector3(0, -1.4, bwidth + width / 2.0);
336  pts[1] = pos + rot * Vector3(0, bheight, bwidth + width / 2.0);
337  pts[2] = pos + rot * Vector3(0, bheight, width / 2.0);
338  pts[3] = pos + rot * Vector3(0, 0, width / 2.0);
339  pts[4] = pos + rot * Vector3(0, 0, -width / 2.0);
340  pts[5] = pos + rot * Vector3(0, bheight, -width / 2.0);
341  pts[6] = pos + rot * Vector3(0, bheight, -bwidth - width / 2.0);
342  pts[7] = pos + rot * Vector3(0, -1.4, -bwidth - width / 2.0);
343  }
344 }
345 
346 inline Vector3 ProceduralRoad::baseOf(Vector3 p)
347 {
348  float y = RoR::App::GetGameContext()->GetTerrain()->GetHeightAt(p.x, p.z) - 0.01;
349 
350  if (y > p.y)
351  {
352  y = p.y - 0.01;
353  }
354 
355  return Vector3(p.x, y, p.z);
356 }
357 
358 void ProceduralRoad::addQuad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, TextureFit texfit, Vector3 pos, Vector3 lastpos, float width, bool flip)
359 {
360  if (vertexcount + 3 >= MAX_VERTEX || tricount * 3 + 3 + 2 >= MAX_TRIS * 3)
361  return;
362  Vector2 texf[4];
363  textureFit(p1, p2, p3, p4, texfit, texf, pos, lastpos, width);
364  //vertexes
365  vertex[vertexcount] = p1;
366  tex[vertexcount] = texf[0];
367  vertex[vertexcount + 1] = p2;
368  tex[vertexcount + 1] = texf[1];
369  vertex[vertexcount + 2] = p3;
370  tex[vertexcount + 2] = texf[2];
371  vertex[vertexcount + 3] = p4;
372  tex[vertexcount + 3] = texf[3];
373  //tris
374  if (flip)
375  {
376  tris[tricount * 3] = vertexcount;
377  tris[tricount * 3 + 1] = vertexcount + 1;
378  tris[tricount * 3 + 2] = vertexcount + 3;
379  tris[tricount * 3 + 3] = vertexcount + 1;
380  tris[tricount * 3 + 3 + 1] = vertexcount + 2;
381  tris[tricount * 3 + 3 + 2] = vertexcount + 3;
382  }
383  else
384  {
385  tris[tricount * 3] = vertexcount;
386  tris[tricount * 3 + 1] = vertexcount + 1;
387  tris[tricount * 3 + 2] = vertexcount + 2;
388  tris[tricount * 3 + 3] = vertexcount;
389  tris[tricount * 3 + 3 + 1] = vertexcount + 2;
390  tris[tricount * 3 + 3 + 2] = vertexcount + 3;
391  }
392  if (collision)
393  {
397  addCollisionQuad(p1, p2, p3, p4, gm, flip);
398  }
399  tricount += 2;
400  vertexcount += 4;
401 }
402 
403 void ProceduralRoad::textureFit(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, TextureFit texfit, Vector2* texc, Vector3 pos, Vector3 lastpos, float width)
404 {
405  int i;
406 
408  {
409  Vector3 ps[4];
410  ps[0] = p1;
411  ps[1] = p2;
412  ps[2] = p3;
413  ps[3] = p4;
414  Vector3 pref1 = pos;
415  Vector3 pref2 = lastpos;
416  //make matrix
417  Vector3 bx = pref2 - pref1;
418  bx.normalise();
419  Vector3 by = Vector3::UNIT_Y;
420  Vector3 bz = bx.crossProduct(by);
421  //coordinates change matrix
422  Matrix3 reverse;
423  reverse.SetColumn(0, bx);
424  reverse.SetColumn(1, by);
425  reverse.SetColumn(2, bz);
426  Matrix3 forward;
427  forward = reverse.Inverse();
428  //transpose
429  for (i = 0; i < 4; i++)
430  {
431  Vector3 trv = forward * (ps[i] - pref1);
432  if (texfit == TextureFit::TEXFIT_BRICKWALL)
433  {
434  float ty = 0.746 - trv.y * 0.25 / 4.5;
435  // fix overlapping
436  if (ty > 1)
437  ty = 1;
438  texc[i] = Vector2(trv.x / 10.0, ty);
439  }
440  if (texfit == TextureFit::TEXFIT_CONCRETEWALL)
441  {
442  // fix overlapping
443  float ty = 0.496 - (trv.y - 0.7) * 0.25 / 4.5;
444  if (ty > 1)
445  ty = 1;
446  texc[i] = Vector2(trv.x / 10.0, ty);
447  }
448  if (texfit == TextureFit::TEXFIT_CONCRETEWALLI)
449  {
450  float ty = 0.496 + trv.y * 0.25 / 4.5;
451  // fix overlapping
452  if (ty > 1)
453  ty = 1;
454  texc[i] = Vector2(trv.x / 10.0, ty);
455  }
456  }
457  return;
458  }
460  {
461  Vector3 ps[4];
462  ps[0] = p1;
463  ps[1] = p2;
464  ps[2] = p3;
465  ps[3] = p4;
466  Vector3 pref1 = pos;
467  Vector3 pref2 = lastpos;
468  //project
469  for (i = 0; i < 4; i++)
470  ps[i].y = 0;
471  pref1.y = 0;
472  pref2.y = 0;
473  //make matrix
474  Vector3 bx = pref2 - pref1;
475  bx.normalise();
476  Vector3 by = Vector3::UNIT_Y;
477  Vector3 bz = bx.crossProduct(by);
478  //coordinates change matrix
479  Matrix3 reverse;
480  reverse.SetColumn(0, bx);
481  reverse.SetColumn(1, by);
482  reverse.SetColumn(2, bz);
483  Matrix3 forward;
484  forward = reverse.Inverse();
485  //transpose
486  float trvrefz = 0.0;
487  for (i = 0; i < 4; i++)
488  {
489  Vector3 trv = forward * (ps[i] - pref1);
490  if (texfit == TextureFit::TEXFIT_CONCRETETOP)
491  {
492  if (i == 0)
493  trvrefz = trv.z;
494  texc[i] = Vector2(trv.x / 10.0, 0.621 + (trv.z - trvrefz) * 0.25 / 4.5);
495  }
496  else
497  {
498  float v1 = 0.072;
499  float v2 = 0.423;
500  if (texfit == TextureFit::TEXFIT_ROADS1)
501  {
502  v1 = 0.001;
503  v2 = 0.036;
504  };
505  if (texfit == TextureFit::TEXFIT_ROADS2)
506  {
507  v1 = 0.036;
508  v2 = 0.072;
509  };
510  if (texfit == TextureFit::TEXFIT_ROADS3)
511  {
512  v1 = 0.423;
513  v2 = 0.458;
514  };
515  if (texfit == TextureFit::TEXFIT_ROADS4)
516  {
517  v1 = 0.458;
518  v2 = 0.493;
519  };
520  if (texfit == TextureFit::TEXFIT_CONCRETEUNDER)
521  {
522  v1 = 0.496;
523  v2 = 0.745;
524  };
525  if (i < 2)
526  texc[i] = Vector2(trv.x / 10.0, v1);
527  else
528  texc[i] = Vector2(trv.x / 10.0, v2);
529  }
530  }
531  return;
532  }
533  //default
534  for (i = 0; i < 4; i++)
535  texc[i] = Vector2(0, 0);
536 }
537 
538 void ProceduralRoad::addCollisionQuad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, ground_model_t* gm, bool flip)
539 {
540  int triID = 0;
541  if (flip)
542  {
543  triID = App::GetGameContext()->GetTerrain()->GetCollisions()->addCollisionTri(p1, p2, p4, gm);
544  if (triID >= 0)
545  registeredCollTris.push_back(triID);
546 
547  triID = App::GetGameContext()->GetTerrain()->GetCollisions()->addCollisionTri(p4, p2, p3, gm);
548  if (triID >= 0)
549  registeredCollTris.push_back(triID);
550  }
551  else
552  {
553  triID = App::GetGameContext()->GetTerrain()->GetCollisions()->addCollisionTri(p1, p2, p3, gm);
554  if (triID >= 0)
555  registeredCollTris.push_back(triID);
556 
557  triID = App::GetGameContext()->GetTerrain()->GetCollisions()->addCollisionTri(p1, p3, p4, gm);
558  if (triID >= 0)
559  registeredCollTris.push_back(triID);
560  }
561 }
562 
563 void ProceduralRoad::addCollisionQuad(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, std::string const& gm_name, bool flip /*= false*/)
564 {
566  if (gm)
567  {
568  this->addCollisionQuad(p1, p2, p3, p4, gm, flip);
569  }
570  else
571  {
572  App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_TERRN, Console::CONSOLE_SYSTEM_WARNING,
573  fmt::format("ProceduralRoad::addCollisionQuad() - ground model '{}' does not exist", gm_name));
574  }
575 }
576 
577 void ProceduralRoad::createMesh()
578 {
579  AxisAlignedBox aab;
580  union
581  {
582  float* vertices;
583  CoVertice_t* covertices;
584  };
586  Ogre::String mesh_name = Ogre::String("RoadSystem-").append(Ogre::StringConverter::toString(mid));
587  msh = MeshManager::getSingleton().createManual(mesh_name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
588 
589  mainsub = msh->createSubMesh();
590  mainsub->setMaterialName("road2");
591 
593  size_t vbufCount = (2 * 3 + 2) * vertexcount;
594  vertices = (float*)malloc(vbufCount * sizeof(float));
595  int i;
596  //fill values
597  for (i = 0; i < vertexcount; i++)
598  {
599  covertices[i].texcoord = tex[i];
600  covertices[i].vertex = vertex[i];
601  //normals are computed later
602  covertices[i].normal = Vector3::ZERO;
603  aab.merge(vertex[i]);
604  }
605 
607  size_t ibufCount = 3 * tricount;
608 
609  //compute normals
610  for (i = 0; i < tricount && i * 3 + 2 < MAX_TRIS * 3; i++)
611  {
612  Vector3 v1, v2;
613  v1 = covertices[tris[i * 3 + 1]].vertex - covertices[tris[i * 3]].vertex;
614  v2 = covertices[tris[i * 3 + 2]].vertex - covertices[tris[i * 3]].vertex;
615  v1 = v1.crossProduct(v2);
616  v1.normalise();
617  covertices[tris[i * 3]].normal += v1;
618  covertices[tris[i * 3 + 1]].normal += v1;
619  covertices[tris[i * 3 + 2]].normal += v1;
620  }
621  //normalize
622  for (i = 0; i < vertexcount; i++)
623  {
624  covertices[i].normal.normalise();
625  }
626 
628  msh->sharedVertexData = new VertexData();
629  msh->sharedVertexData->vertexCount = vertexcount;
630 
632  VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration;
633  size_t offset = 0;
634  decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
635  offset += VertexElement::getTypeSize(VET_FLOAT3);
636  decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
637  offset += VertexElement::getTypeSize(VET_FLOAT3);
638  decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
639  offset += VertexElement::getTypeSize(VET_FLOAT2);
640 
643  HardwareVertexBufferSharedPtr vbuf =
644  HardwareBufferManager::getSingleton().createVertexBuffer(
645  offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
646 
648  vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
649 
651  VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
652  bind->setBinding(0, vbuf);
653 
654  //for the face
656  HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
657  createIndexBuffer(
658  HardwareIndexBuffer::IT_16BIT,
659  ibufCount,
660  HardwareBuffer::HBU_STATIC_WRITE_ONLY);
661 
663  ibuf->writeData(0, ibuf->getSizeInBytes(), tris, true);
664 
666  mainsub->useSharedVertices = true;
667  mainsub->indexData->indexBuffer = ibuf;
668  mainsub->indexData->indexCount = ibufCount;
669  mainsub->indexData->indexStart = 0;
670 
671  msh->_setBounds(aab, true);
672 
674  msh->load();
675 
676  free(vertices);
677 };
Script2Game::ROAD_LEFT
@ ROAD_LEFT
Definition: ProceduralRoadClass.h:16
GameContext.h
Game state manager and message-queue provider.
Script2Game::TEXFIT_CONCRETEUNDER
@ TEXFIT_CONCRETEUNDER
Definition: ProceduralRoadClass.h:35
Script2Game::ROAD_AUTOMATIC
@ ROAD_AUTOMATIC
Definition: ProceduralRoadClass.h:14
Script2Game::TEXFIT_BRICKWALL
@ TEXFIT_BRICKWALL
Definition: ProceduralRoadClass.h:26
Script2Game::TEXFIT_CONCRETEWALLI
@ TEXFIT_CONCRETEWALLI
Definition: ProceduralRoadClass.h:33
y
float y
Definition: (ValueTypes) quaternion.h:6
Script2Game::TEXFIT_ROAD
@ TEXFIT_ROAD
Definition: ProceduralRoadClass.h:29
format
Truck file format(technical spec)
Script2Game::TEXFIT_ROADS2
@ TEXFIT_ROADS2
Definition: ProceduralRoadClass.h:28
Console.h
RoR::ProceduralRoad::CoVertice_t::texcoord
Ogre::Vector2 texcoord
Definition: ProceduralRoad.h:92
RoR::Console::putMessage
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
Definition: Console.cpp:97
RoR::Collisions::registerCollisionMesh
void registerCollisionMesh(Ogre::String const &srcname, Ogre::String const &meshname, Ogre::Vector3 const &pos, Ogre::AxisAlignedBox bounding_box, ground_model_t *gm, int ctri_start, int ctri_count)
Mark already generated collision tris as belonging to (virtual) mesh.
Definition: Collisions.cpp:1455
Script2Game::ROAD_RIGHT
@ ROAD_RIGHT
Definition: ProceduralRoadClass.h:17
Script2Game::TEXFIT_ROADS3
@ TEXFIT_ROADS3
Definition: ProceduralRoadClass.h:30
RoR::Collisions::removeCollisionTri
void removeCollisionTri(int number)
Definition: Collisions.cpp:356
Actor.h
RoR::TextureFit
TextureFit
Definition: ProceduralRoad.h:44
RoR::GfxScene::GetSceneManager
Ogre::SceneManager * GetSceneManager()
Definition: GfxScene.h:64
Script2Game::ROAD_BOTH
@ ROAD_BOTH
Definition: ProceduralRoadClass.h:18
RoR::Terrain::GetHeightAt
float GetHeightAt(float x, float z)
Definition: Terrain.cpp:503
ProceduralRoad.h
Script2Game::ROAD_BRIDGE
@ ROAD_BRIDGE
Definition: ProceduralRoadClass.h:19
RoR::RoadType
RoadType
Definition: ProceduralRoad.h:33
RoR::Str
Wrapper for classic c-string (local buffer) Refresher: strlen() excludes '\0' terminator; strncat() A...
Definition: Str.h:35
RoR::Collisions::getGroundModelByString
ground_model_t * getGroundModelByString(const Ogre::String name)
Definition: Collisions.cpp:365
Script2Game::ROAD_FLAT
@ ROAD_FLAT
Definition: ProceduralRoadClass.h:15
id_counter
static int id_counter
Definition: ProceduralRoad.cpp:36
RoR::Str::ToCStr
const char * ToCStr() const
Definition: Str.h:46
RoR::Terrain::GetCollisions
Collisions * GetCollisions()
Definition: Terrain.h:83
GfxScene.h
RoR::Collisions::addCollisionTri
int addCollisionTri(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, ground_model_t *gm)
Definition: Collisions.cpp:551
Script2Game::TEXFIT_ROADS1
@ TEXFIT_ROADS1
Definition: ProceduralRoadClass.h:27
Script2Game::TEXFIT_CONCRETEWALL
@ TEXFIT_CONCRETEWALL
Definition: ProceduralRoadClass.h:32
Application.h
Central state/object manager and communications hub.
RoR::App::GetConsole
Console * GetConsole()
Definition: Application.cpp:270
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:280
Script2Game::TEXFIT_ROADS4
@ TEXFIT_ROADS4
Definition: ProceduralRoadClass.h:31
Script2Game::TEXFIT_NONE
@ TEXFIT_NONE
Definition: ProceduralRoadClass.h:25
by
or anywhere else will not be considered a but parsed as regular data ! Each line is treated as values separated by separators Possible i e animators Multiline description Single does not affect it Directive usualy set global attributes or change behavior of the parsing Directive may appear in any block section Modularity The elements can be grouped into modules Each module must belong to one or more configurations Directives sectionconfig specify truck configurations the user can choose from Exactly one must be selected If the first defined is used lettercase matches original docs(parsing is insensitive). NAME TYPE NOTES advdrag BLOCK add_animation DIRECTIVE Special syntax airbrakes BLOCK animators BLOCK Special syntax IF(values[0]=="") bad trailing chars are silently ignored no space at the end Items delimited by
Definition: ReadMe.txt:293
Script2Game::TEXFIT_CONCRETETOP
@ TEXFIT_CONCRETETOP
Definition: ProceduralRoadClass.h:34
RoR::ground_model_t
Surface friction properties.
Definition: SimData.h:739
Terrain.h
Ogre
Definition: ExtinguishableFireAffector.cpp:35
Collisions.h
RoR::App::diag_terrn_log_roads
CVar * diag_terrn_log_roads
Definition: Application.cpp:157
Script2Game::ROAD_MONORAIL
@ ROAD_MONORAIL
Definition: ProceduralRoadClass.h:20
RoR::ProceduralRoad::CoVertice_t
Definition: ProceduralRoad.h:88
RoR
Definition: AppContext.h:36
RoR::App::GetGfxScene
GfxScene * GetGfxScene()
Definition: Application.cpp:276
Log
quaternion Log() const
RoR::GameContext::GetTerrain
const TerrainPtr & GetTerrain()
Definition: GameContext.h:117