RigsofRods
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
FlexBody.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-2020 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 "FlexBody.h"
23 
24 #include "Application.h"
25 #include "ApproxMath.h"
26 #include "Console.h"
27 #include "SimData.h"
28 #include "FlexFactory.h"
29 #include "GfxActor.h"
30 #include "GfxScene.h"
31 #include "RigDef_File.h"
32 
33 #include <Ogre.h>
34 
35 using namespace Ogre;
36 using namespace RoR;
37 
38 FlexBody::FlexBody(
39  RoR::FlexBodyCacheData* preloaded_from_cache,
40  RoR::GfxActor* gfx_actor,
41  Ogre::Entity* ent,
42  NodeNum_t ref,
43  NodeNum_t nx,
44  NodeNum_t ny,
45  Ogre::Vector3 offset,
46  Ogre::Quaternion const & rot,
47  std::vector<unsigned int> & node_indices,
48  std::vector<ForvertTempData>& forvert_data
49 ):
50  m_center_offset(offset)
51  , m_node_center(ref)
52  , m_node_x(nx)
53  , m_node_y(ny)
54  , m_scene_entity(ent)
55  , m_gfx_actor(gfx_actor)
56 {
59 
60  Ogre::Vector3* vertices = nullptr;
61  std::string mesh_name = ent->getMesh()->getName();
62 
63  Vector3 normal = Vector3::UNIT_Y;
64  Vector3 position = Vector3::ZERO;
65  Quaternion orientation = Quaternion::ZERO;
66 
68 
70  {
71  Vector3 diffX = nodes[nx].AbsPosition-nodes[ref].AbsPosition;
72  Vector3 diffY = nodes[ny].AbsPosition-nodes[ref].AbsPosition;
73 
74  normal = (diffY.crossProduct(diffX)).normalisedCopy();
75 
76  // position
77  position = nodes[ref].AbsPosition + offset.x * diffX + offset.y * diffY;
78  position = position + offset.z * normal;
79 
80  // orientation
81  Vector3 refX = diffX.normalisedCopy();
82  Vector3 refY = refX.crossProduct(normal);
83  orientation = Quaternion(refX, normal, refY) * rot;
84  }
85  else
86  {
87  // special case!
88  normal = Vector3::UNIT_Y;
89  position = nodes[0].AbsPosition + offset;
90  orientation = rot;
91  }
92 
93  Ogre::MeshPtr mesh=ent->getMesh();
94  m_orig_mesh_info = RoR::PrintMeshInfo("Original", mesh); // For diagnostics only
95  int num_submeshes = static_cast<int>(mesh->getNumSubMeshes());
96  if (preloaded_from_cache == nullptr)
97  {
98  //determine if we have texture coordinates everywhere
99  if (mesh->sharedVertexData && mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES)==0)
100  {
101  m_has_texture=false;
102  }
103  for (int i=0; i<num_submeshes; i++)
104  {
105  if (!mesh->getSubMesh(i)->useSharedVertices && mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES)==0)
106  {
107  m_has_texture=false;
108  }
109  }
110  if (!m_has_texture)
111  {
112  LOG("FLEXBODY Warning: at least one part of this mesh does not have texture coordinates, switching off texturing!");
113  m_has_texture_blend=false;
114  }
115 
116  //detect the anomalous case where a mesh is exported without normal vectors
117  bool havenormal=true;
118  if (mesh->sharedVertexData && mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)==0)
119  {
120  havenormal=false;
121  }
122  for (int i=0; i<num_submeshes; i++)
123  {
124  if (!mesh->getSubMesh(i)->useSharedVertices && mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)==0)
125  {
126  havenormal=false;
127  }
128  }
129  if (!havenormal)
130  {
131  LOG("FLEXBODY Error: at least one part of this mesh does not have normal vectors, export your mesh with normal vectors! Disabling flexbody");
132  // NOTE: Intentionally not disabling, for compatibility with v0.4.0.7
133  }
134  }
135  else
136  {
139  }
140 
141  //create optimal VertexDeclaration
142  VertexDeclaration* optimalVD=HardwareBufferManager::getSingleton().createVertexDeclaration();
143  optimalVD->addElement(0, 0, VET_FLOAT3, VES_POSITION);
144  optimalVD->addElement(1, 0, VET_FLOAT3, VES_NORMAL);
145  if (m_has_texture_blend) optimalVD->addElement(2, 0, VET_COLOUR_ARGB, VES_DIFFUSE);
146  if (m_has_texture) optimalVD->addElement(3, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
147  optimalVD->sort();
148  optimalVD->closeGapsInSource();
149  BufferUsageList optimalBufferUsages;
150  for (size_t u = 0; u <= optimalVD->getMaxSource(); ++u)
151  {
152  optimalBufferUsages.push_back(HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
153  }
154 
155  //adding color buffers, well get the reference later
157  {
158  if (mesh->sharedVertexData)
159  {
160  if (mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)==0)
161  {
162  //add buffer
163  int index=mesh->sharedVertexData->vertexDeclaration->getMaxSource()+1;
164  mesh->sharedVertexData->vertexDeclaration->addElement(index, 0, VET_COLOUR_ARGB, VES_DIFFUSE);
165  mesh->sharedVertexData->vertexDeclaration->sort();
166  index=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
167  HardwareVertexBufferSharedPtr vbuf=HardwareBufferManager::getSingleton().createVertexBuffer(VertexElement::getTypeSize(VET_COLOUR_ARGB), mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
168  mesh->sharedVertexData->vertexBufferBinding->setBinding(index, vbuf);
169  }
170  }
171  for (int i=0; i<num_submeshes; i++)
172  {
173  if (!mesh->getSubMesh(i)->useSharedVertices)
174  {
175  Ogre::VertexData* vertex_data = mesh->getSubMesh(i)->vertexData;
176  Ogre::VertexDeclaration* vertex_decl = vertex_data->vertexDeclaration;
177  if (vertex_decl->findElementBySemantic(VES_DIFFUSE)==0)
178  {
179  //add buffer
180  int index = vertex_decl->getMaxSource()+1;
181  vertex_decl->addElement(index, 0, VET_COLOUR_ARGB, VES_DIFFUSE);
182  vertex_decl->sort();
183  vertex_decl->findElementBySemantic(VES_DIFFUSE)->getSource();
184  HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
185  VertexElement::getTypeSize(VET_COLOUR_ARGB), vertex_data->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
186  vertex_data->vertexBufferBinding->setBinding(index, vbuf);
187  }
188  }
189  }
190  }
191 
192  //reorg
193  //LOG("FLEXBODY reorganizing buffers");
194  if (mesh->sharedVertexData)
195  {
196  mesh->sharedVertexData->reorganiseBuffers(optimalVD, optimalBufferUsages);
197  mesh->sharedVertexData->removeUnusedBuffers();
198  mesh->sharedVertexData->closeGapsInBindings();
199  }
200  Mesh::SubMeshIterator smIt = mesh->getSubMeshIterator();
201  while (smIt.hasMoreElements())
202  {
203  SubMesh* sm = smIt.getNext();
204  if (!sm->useSharedVertices)
205  {
206  sm->vertexData->reorganiseBuffers(optimalVD->clone(), optimalBufferUsages);
207  sm->vertexData->removeUnusedBuffers();
208  sm->vertexData->closeGapsInBindings();
209  }
210  }
211 
212  //print mesh information
213  //LOG("FLEXBODY Printing modififed mesh informations:");
214  //printMeshInfo(ent->getMesh().get());
215 
216  //get the buffers
217  //getMeshInformation(ent->getMesh().get(),m_vertex_count,vertices,index_count,indices, position, orientation, Vector3(1,1,1));
218 
219  //getting vertex counts
220  if (preloaded_from_cache == nullptr)
221  {
222  m_vertex_count=0;
225  if (mesh->sharedVertexData)
226  {
227  m_vertex_count+=mesh->sharedVertexData->vertexCount;
229  }
230  for (int i=0; i<num_submeshes; i++)
231  {
232  if (!mesh->getSubMesh(i)->useSharedVertices)
233  {
234  m_vertex_count+=mesh->getSubMesh(i)->vertexData->vertexCount;
236  }
237  }
238  } else
239  {
240  m_vertex_count = preloaded_from_cache->header.vertex_count;
242  m_num_submesh_vbufs = preloaded_from_cache->header.num_submesh_vbufs;
243  }
244 
245  // Profiler data
246  double stat_manual_buffers_created_time = -1;
247  double stat_transformed_time = -1;
248  double stat_located_time = -1;
249  if (preloaded_from_cache != nullptr)
250  {
251  m_dst_pos = preloaded_from_cache->dst_pos;
252  m_src_normals = preloaded_from_cache->src_normals;
253  m_locators = preloaded_from_cache->locators;
254  m_dst_normals = (Vector3*)malloc(sizeof(Vector3)*m_vertex_count); // Use malloc() for compatibility
255 
257  {
258  m_src_colors = preloaded_from_cache->src_colors;
259  }
260 
261  if (mesh->sharedVertexData)
262  {
263  m_shared_buf_num_verts=(int)mesh->sharedVertexData->vertexCount;
264 
265  //vertices
266  int source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
267  m_shared_vbuf_pos=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
268  //normals
269  source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
270  m_shared_vbuf_norm=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
271  //colors
273  {
274  source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
275  m_shared_vbuf_color=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
276  }
277  }
278  unsigned int curr_submesh_idx = 0;
279  for (int i=0; i<num_submeshes; i++)
280  {
281  const Ogre::SubMesh* submesh = mesh->getSubMesh(i);
282  if (submesh->useSharedVertices)
283  {
284  continue;
285  }
286  const Ogre::VertexData* vertex_data = submesh->vertexData;
287  m_submesh_vbufs_vertex_counts[curr_submesh_idx] = (int)vertex_data->vertexCount;
288 
289  int source_pos = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
290  int source_norm = vertex_data->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
291  m_submesh_vbufs_pos [curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_pos);
292  m_submesh_vbufs_norm[curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_norm);
293 
295  {
296  int source_color = vertex_data->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
297  m_submesh_vbufs_color[curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_color);
298  }
299  curr_submesh_idx++;
300  }
301  }
302  else
303  {
304  vertices=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count);
305  m_dst_pos=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count);
306  m_src_normals=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count);
307  m_dst_normals=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count);
309  {
310  m_src_colors=(ARGB*)malloc(sizeof(ARGB)*m_vertex_count);
311  for (int i=0; i<(int)m_vertex_count; i++) m_src_colors[i]=0x00000000;
312  }
313  Vector3* vpt=vertices;
314  Vector3* npt=m_src_normals;
315  if (mesh->sharedVertexData)
316  {
317  m_shared_buf_num_verts=(int)mesh->sharedVertexData->vertexCount;
318  //vertices
319  int source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
320  m_shared_vbuf_pos=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
321  m_shared_vbuf_pos->readData(0, mesh->sharedVertexData->vertexCount*sizeof(Vector3), (void*)vpt);
322  vpt+=mesh->sharedVertexData->vertexCount;
323  //normals
324  source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
325  m_shared_vbuf_norm=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
326  m_shared_vbuf_norm->readData(0, mesh->sharedVertexData->vertexCount*sizeof(Vector3), (void*)npt);
327  npt+=mesh->sharedVertexData->vertexCount;
328  //colors
330  {
331  source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
332  m_shared_vbuf_color=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
333  m_shared_vbuf_color->writeData(0, mesh->sharedVertexData->vertexCount*sizeof(ARGB), (void*)m_src_colors);
334  }
335  }
336  int cursubmesh=0;
337  for (int i=0; i<num_submeshes; i++)
338  {
339  const Ogre::SubMesh* submesh = mesh->getSubMesh(i);
340  if (submesh->useSharedVertices)
341  {
342  continue;
343  }
344  const Ogre::VertexData* vertex_data = submesh->vertexData;
345  int vertex_count = (int)vertex_data->vertexCount;
346  m_submesh_vbufs_vertex_counts[cursubmesh] = vertex_count;
347  //vertices
348  int source = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
349  m_submesh_vbufs_pos[cursubmesh]=vertex_data->vertexBufferBinding->getBuffer(source);
350  m_submesh_vbufs_pos[cursubmesh]->readData(0, vertex_count*sizeof(Vector3), (void*)vpt);
351  vpt += vertex_count;
352  //normals
353  source = vertex_data->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
354  m_submesh_vbufs_norm[cursubmesh]=vertex_data->vertexBufferBinding->getBuffer(source);
355  m_submesh_vbufs_norm[cursubmesh]->readData(0, vertex_count*sizeof(Vector3), (void*)npt);
356  npt += vertex_count;
357  //colors
359  {
360  source = vertex_data->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
361  m_submesh_vbufs_color[cursubmesh] = vertex_data->vertexBufferBinding->getBuffer(source);
362  m_submesh_vbufs_color[cursubmesh]->writeData(0, vertex_count*sizeof(ARGB), (void*)m_src_colors);
363  }
364  cursubmesh++;
365  }
366 
367  //transform
368  for (int i=0; i<(int)m_vertex_count; i++)
369  {
370  vertices[i]=(orientation*vertices[i])+position;
371  }
372 
374  for (int i=0; i<(int)m_vertex_count; i++)
375  {
376  // Is this locator is manually specified via directive 'forvert'?
377  auto forvert_itor = std::find_if(forvert_data.begin(), forvert_data.end(),
378  [i](const ForvertTempData& data) { return data.vert_index == i; });
379  if (forvert_itor != forvert_data.end())
380  {
381  m_locators[i].ref = forvert_itor->nref;
382  m_locators[i].nx = forvert_itor->nx;
383  m_locators[i].ny = forvert_itor->ny;
384  m_locators[i].is_forvert = true;
385  LOG(fmt::format("FLEXBODY vertex {} overriden for nodes REF:{}, VX:{}, VY:{}",
386  i, m_locators[i].ref, m_locators[i].nx, m_locators[i].ny));
387  }
388  else
389  {
390 
391  //search nearest node as the local origin
392  float closest_node_distance = std::numeric_limits<float>::max();
393  int closest_node_index = -1;
394  for (auto node_index : node_indices)
395  {
396  float node_distance = vertices[i].squaredDistance(nodes[node_index].AbsPosition);
397  if (node_distance < closest_node_distance)
398  {
399  closest_node_distance = node_distance;
400  closest_node_index = node_index;
401  }
402  }
403  if (closest_node_index == -1)
404  {
405  LOG("FLEXBODY ERROR on mesh " + mesh_name + ": REF node not found");
406  closest_node_index = 0;
407  }
408  m_locators[i].ref = closest_node_index;
409 
410  //search the second nearest node as the X vector
411  closest_node_distance = std::numeric_limits<float>::max();
412  closest_node_index = -1;
413  for (auto node_index : node_indices)
414  {
415  if (node_index == m_locators[i].ref)
416  {
417  continue;
418  }
419  float node_distance = vertices[i].squaredDistance(nodes[node_index].AbsPosition);
420  if (node_distance < closest_node_distance)
421  {
422  closest_node_distance = node_distance;
423  closest_node_index = node_index;
424  }
425  }
426  if (closest_node_index == -1)
427  {
428  LOG("FLEXBODY ERROR on mesh " + mesh_name + ": VX node not found");
429  closest_node_index = 0;
430  }
431  m_locators[i].nx = closest_node_index;
432 
433  //search another close, orthogonal node as the Y vector
434  closest_node_distance = std::numeric_limits<float>::max();
435  closest_node_index = -1;
436  Vector3 vx = (nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition).normalisedCopy();
437  for (auto node_index : node_indices)
438  {
439  if (node_index == m_locators[i].ref || node_index == m_locators[i].nx)
440  {
441  continue;
442  }
443  float node_distance = vertices[i].squaredDistance(nodes[node_index].AbsPosition);
444  if (node_distance < closest_node_distance)
445  {
446  Vector3 vt = (nodes[node_index].AbsPosition - nodes[m_locators[i].ref].AbsPosition).normalisedCopy();
447  float cost = vx.dotProduct(vt);
448  if (std::abs(cost) > std::sqrt(2.0f) / 2.0f)
449  {
450  continue; //rejection, fails the orthogonality criterion (+-45 degree)
451  }
452  closest_node_distance = node_distance;
453  closest_node_index = node_index;
454  }
455  }
456  if (closest_node_index == -1)
457  {
458  LOG("FLEXBODY ERROR on mesh " + mesh_name + ": VY node not found");
459  closest_node_index = 0;
460  }
461  m_locators[i].ny = closest_node_index;
462  }
463 
464  Matrix3 mat;
465  Vector3 diffX = nodes[m_locators[i].nx].AbsPosition-nodes[m_locators[i].ref].AbsPosition;
466  Vector3 diffY = nodes[m_locators[i].ny].AbsPosition-nodes[m_locators[i].ref].AbsPosition;
467 
468  mat.SetColumn(0, diffX);
469  mat.SetColumn(1, diffY);
470  mat.SetColumn(2, (diffX.crossProduct(diffY)).normalisedCopy()); // Old version: mat.SetColumn(2, nodes[loc.nz].AbsPosition-nodes[loc.ref].AbsPosition);
471 
472  mat = mat.Inverse();
473 
474  //compute coordinates in the newly formed Euclidean basis
475  m_locators[i].coords = mat * (vertices[i] - nodes[m_locators[i].ref].AbsPosition);
476 
477  // that's it!
478  }
479 
480  } // if (preloaded_from_cache == nullptr)
481 
482  //adjusting bounds
483  AxisAlignedBox aab=mesh->getBounds();
484  Vector3 v=aab.getMinimum();
485  float mi=v.x;
486  if (v.y<mi) mi=v.y;
487  if (v.z<mi) mi=v.z;
488  mi=fabs(mi);
489  v=aab.getMaximum();
490  float ma=v.x;
491  if (ma<v.y) ma=v.y;
492  if (ma<v.z) ma=v.z;
493  ma=fabs(ma);
494  if (mi>ma) ma=mi;
495  aab.setMinimum(Vector3(-ma,-ma,-ma));
496  aab.setMaximum(Vector3(ma,ma,ma));
497  mesh->_setBounds(aab, true);
498 
499  //okay, show the mesh now
500  m_scene_node=App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode();
501  m_scene_node->attachObject(ent);
502  m_scene_node->setPosition(position);
503 
504  if (preloaded_from_cache == nullptr)
505  {
506  for (int i=0; i<(int)m_vertex_count; i++)
507  {
508  Matrix3 mat;
509  Vector3 diffX = nodes[m_locators[i].nx].AbsPosition-nodes[m_locators[i].ref].AbsPosition;
510  Vector3 diffY = nodes[m_locators[i].ny].AbsPosition-nodes[m_locators[i].ref].AbsPosition;
511 
512  mat.SetColumn(0, diffX);
513  mat.SetColumn(1, diffY);
514  mat.SetColumn(2, diffX.crossProduct(diffY).normalisedCopy()); // Old version: mat.SetColumn(2, nodes[loc.nz].AbsPosition-nodes[loc.ref].AbsPosition);
515 
516  mat = mat.Inverse();
517 
518  // compute coordinates in the Euclidean basis
519  m_src_normals[i] = mat*(orientation * m_src_normals[i]);
520  }
521  }
522 
523  if (vertices != nullptr) { free(vertices); }
524 
525  // Keep the forset nodes for diagnostics
526  for (unsigned int nodenum : node_indices)
527  {
528  m_forset_nodes.push_back((NodeNum_t)nodenum);
529  }
530 
531  if (App::GetConsole()->cVarGet("flexbody_defrag_enabled", CVAR_TYPE_BOOL)->getBool()
532  // For simplicity, only take 1-submesh meshes (almost always the case anyway)
533  && m_scene_entity->getMesh()->getNumSubMeshes() == 1)
534  {
535  this->defragmentFlexbodyMesh();
536  }
537 }
538 
539 FlexBody::FlexBody(PlaceholderType p_type, FlexbodyID_t id, const std::string& orig_meshname)
540 {
542  m_id = id;
543  m_orig_mesh_name = orig_meshname;
544  m_placeholder_type = p_type;
545 }
546 
548 {
549  // Stuff using <new>
550  if (m_locators != nullptr) { delete[] m_locators; }
551  // Stuff using malloc()
552  if (m_src_normals != nullptr) { free(m_src_normals); }
553  if (m_dst_normals != nullptr) { free(m_dst_normals); }
554  if (m_dst_pos != nullptr) { free(m_dst_pos ); }
555  if (m_src_colors != nullptr) { free(m_src_colors ); }
556 
557  this->destroyOgreObjects();
558 }
559 
561 {
562  switch (type)
563  {
564  case PlaceholderType::NOT_A_PLACEHOLDER: return "NOT_A_PLACEHOLDER";
565  case PlaceholderType::TUNING_REMOVED_PLACEHOLDER: return "TUNING_REMOVED_PLACEHOLDER";
566  case PlaceholderType::FAULTY_FORSET_PLACEHOLDER: return "FAULTY_FORSET_PLACEHOLDER";
567  case PlaceholderType::FAULTY_MESH_PLACEHOLDER: return "FAULTY_MESH_PLACEHOLDER";
568  default: return "";
569  }
570 }
571 
573 {
574  // Separated out from destructor so that exceptions can be handled separately (C++ destructor cannot propagate exceptions)
575  // -----------------------------------------------------------------------------------------------------------------------
576 
577  // OGRE resource - scene node
578  if (m_scene_node != nullptr)
579  {
580  m_scene_node->getParentSceneNode()->removeChild(m_scene_node);
581  App::GetGfxScene()->GetSceneManager()->destroySceneNode(m_scene_node);
582  }
583  m_scene_node = nullptr;
584 
585  // OGRE resource - scene entity
586  if (m_scene_entity != nullptr)
587  {
588  Ogre::MeshPtr mesh = m_scene_entity->getMesh();
589  App::GetGfxScene()->GetSceneManager()->destroyEntity(m_scene_entity);
590 
591  // OGRE resource - mesh (unique copy - should be destroyed)
592  Ogre::MeshManager::getSingleton().remove(mesh->getHandle());
593  }
594  m_scene_entity = nullptr;
595 }
596 
598 {
599  // Scene node is NULL if disabled via addonpart/tuneup.
600  return m_scene_node
601  && m_scene_node->isInSceneGraph()
602  && m_scene_node->getAttachedObject(0)->isVisible();
603 
604 }
605 
606 void FlexBody::setVisible(bool visible)
607 {
608  // Scene node is NULL if disabled via addonpart/tuneup.
609  if (m_scene_node)
610  m_scene_node->setVisible(visible);
611 }
612 
614 {
615  // Scene entity is NULL if disabled via addonpart/tuneup.
616  if (m_scene_entity)
617  m_scene_entity->setCastShadows(val);
618 }
619 
621 {
623 
625 
626  // compute the local center
627  if (m_node_center >= 0)
628  {
629  Vector3 diffX = nodes[m_node_x].AbsPosition - nodes[m_node_center].AbsPosition;
630  Vector3 diffY = nodes[m_node_y].AbsPosition - nodes[m_node_center].AbsPosition;
631  Ogre::Vector3 flexit_normal = fast_normalise(diffY.crossProduct(diffX));
632 
633  m_flexit_center = nodes[m_node_center].AbsPosition + m_center_offset.x * diffX + m_center_offset.y * diffY;
634  m_flexit_center += m_center_offset.z * flexit_normal;
635  }
636  else
637  {
638  m_flexit_center = nodes[0].AbsPosition;
639  }
640 
641  for (int i=0; i<(int)m_vertex_count; i++)
642  {
643  Vector3 diffX = nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition;
644  Vector3 diffY = nodes[m_locators[i].ny].AbsPosition - nodes[m_locators[i].ref].AbsPosition;
645  Vector3 nCross = fast_normalise(diffX.crossProduct(diffY)); //nCross.normalise();
646 
647  m_dst_pos[i].x = diffX.x * m_locators[i].coords.x + diffY.x * m_locators[i].coords.y + nCross.x * m_locators[i].coords.z;
648  m_dst_pos[i].y = diffX.y * m_locators[i].coords.x + diffY.y * m_locators[i].coords.y + nCross.y * m_locators[i].coords.z;
649  m_dst_pos[i].z = diffX.z * m_locators[i].coords.x + diffY.z * m_locators[i].coords.y + nCross.z * m_locators[i].coords.z;
650 
651  m_dst_pos[i] += nodes[m_locators[i].ref].AbsPosition - m_flexit_center;
652 
653  m_dst_normals[i].x = diffX.x * m_src_normals[i].x + diffY.x * m_src_normals[i].y + nCross.x * m_src_normals[i].z;
654  m_dst_normals[i].y = diffX.y * m_src_normals[i].x + diffY.y * m_src_normals[i].y + nCross.y * m_src_normals[i].z;
655  m_dst_normals[i].z = diffX.z * m_src_normals[i].x + diffY.z * m_src_normals[i].y + nCross.z * m_src_normals[i].z;
656 
658  }
659 }
660 
662 {
663  if (!m_scene_node) // Disabled via addonpart/tuneup
664  return;
665 
666  Vector3 *ppt = m_dst_pos;
667  Vector3 *npt = m_dst_normals;
669  {
670  m_shared_vbuf_pos->writeData(0, m_shared_buf_num_verts*sizeof(Vector3), ppt, true);
671  ppt += m_shared_buf_num_verts;
672  m_shared_vbuf_norm->writeData(0, m_shared_buf_num_verts*sizeof(Vector3), npt, true);
673  npt += m_shared_buf_num_verts;
674  }
675  for (int i=0; i<m_num_submesh_vbufs; i++)
676  {
677  m_submesh_vbufs_pos[i]->writeData(0, m_submesh_vbufs_vertex_counts[i]*sizeof(Vector3), ppt, true);
679  m_submesh_vbufs_norm[i]->writeData(0, m_submesh_vbufs_vertex_counts[i]*sizeof(Vector3), npt, true);
681  }
682 
683  if (m_blend_changed)
684  {
685  writeBlend();
686  m_blend_changed = false;
687  }
688 
689  m_scene_node->setPosition(m_flexit_center);
690 }
691 
693 {
695  {
696  for (int i=0; i<(int)m_vertex_count; i++) m_src_colors[i]=0x00000000;
697  writeBlend();
698  }
699 }
700 
702 {
703  if (!m_has_texture_blend) return;
704  ARGB *cpt = m_src_colors;
706  {
707  m_shared_vbuf_color->writeData(0, m_shared_buf_num_verts*sizeof(ARGB), (void*)cpt, true);
709  }
710  for (int i=0; i<m_num_submesh_vbufs; i++)
711  {
712  m_submesh_vbufs_color[i]->writeData(0, m_submesh_vbufs_vertex_counts[i]*sizeof(ARGB), (void*)cpt, true);
714  }
715 }
716 
717 void FlexBody::updateBlend() //so easy!
718 {
720  for (int i=0; i<(int)m_vertex_count; i++)
721  {
722  RoR::NodeSB *nd = &nodes[m_locators[i].ref];
723  ARGB col = m_src_colors[i];
724  if (nd->nd_has_contact && !(col&0xFF000000))
725  {
726  m_src_colors[i]=col|0xFF000000;
727  m_blend_changed = true;
728  }
729  if (nd->nd_is_wet ^ ((col&0x000000FF)>0))
730  {
731  m_src_colors[i]=(col&0xFFFFFF00)+0x000000FF*nd->nd_is_wet;
732  m_blend_changed = true;
733  }
734  }
735 }
736 
738 {
739  if (a > b)
740  {
743  }
744  else if (a < b)
745  {
748  }
749  else
750  {
751  return 0;
752  }
753 }
754 
756 {
757  return 0
762  + evalNodeDistance(a.getMean(), b.getMean());
763 }
764 
765 template<typename uint_T> void reorderIndexBuffer(Ogre::IndexData* idx_data, std::vector<int> const& new_index_lookup)
766 {
767  uint_T* workibuf = new uint_T[idx_data->indexCount];
768  idx_data->indexBuffer->readData(0, idx_data->indexBuffer->getSizeInBytes(), workibuf);
769  for (size_t i = 0; i < idx_data->indexCount; i++)
770  {
771  workibuf[i] = new_index_lookup[workibuf[i]];
772  }
773  idx_data->indexBuffer->writeData(0, idx_data->indexBuffer->getSizeInBytes(), workibuf);
774  delete[] workibuf;
775 }
776 
777 void reorderVertexBuffer(Ogre::HardwareVertexBufferSharedPtr vert_buf, const Ogre::VertexElement* vert_elem, std::vector<int> const& new_index_lookup)
778 {
779  char* workbuf_src = new char[vert_buf->getSizeInBytes()];
780  char* workbuf_dst = new char[vert_buf->getSizeInBytes()];
781  vert_buf->readData(0, vert_buf->getSizeInBytes(), workbuf_src);
782  for (size_t i = 0; i < vert_buf->getNumVertices(); i++)
783  {
784  void* src = workbuf_src + (i * vert_elem->getSize());
785  void* dst = workbuf_dst + (new_index_lookup[i] * vert_elem->getSize());
786  std::memcpy(dst, src, vert_elem->getSize());
787  }
788  vert_buf->writeData(0, vert_buf->getSizeInBytes(), workbuf_dst);
789  delete[] workbuf_src;
790  delete[] workbuf_dst;
791 }
792 
794 {
795  // Analysis
796  NodeNum_t forset_max = std::numeric_limits<NodeNum_t>::min();
797  NodeNum_t forset_min = std::numeric_limits<NodeNum_t>::max();
798  for (NodeNum_t n : this->getForsetNodes())
799  {
800  if (n > forset_max) { forset_max = n; }
801  if (n < forset_min) { forset_min = n; }
802  }
803 
804  std::vector<int> new_index_lookup(m_vertex_count);
805  for (int i = 0; i < (int)m_vertex_count; i++)
806  {
807  new_index_lookup[i] = i;
808  }
809 
810  Locator_t prev_loc;
811  // edge values to start with
812  prev_loc.ref = forset_min;
813  prev_loc.nx = forset_min;
814  prev_loc.ny = forset_min;
815 
816  // SELECTION SORT (https://www.geeksforgeeks.org/selection-sort/)
817  for (int i = 0; i < m_vertex_count; i++)
818  {
819  // Find the next locator closest in memory
820  int closest_loc = i;
821  int closest_loc_penalty = INT_MAX;
822  for (int j = i; j < m_vertex_count; j++)
823  {
824  int penalty = evalMemoryDistance(prev_loc, m_locators[j]);
825  if (penalty < closest_loc_penalty)
826  {
827  closest_loc_penalty = penalty;
828  closest_loc = j;
829  }
830  }
831 
832  // Swap locators+normals in memory, update lookup
833  Locator_t loc_tmp = m_locators[closest_loc];
834  Ogre::Vector3 norm_tmp = m_src_normals[closest_loc];
835  int idx_tmp = new_index_lookup[closest_loc];
836 
837  m_locators[closest_loc] = m_locators[i];
838  m_src_normals[closest_loc] = m_src_normals[i];
839  new_index_lookup[closest_loc] = new_index_lookup[i];
840 
841  m_locators[i] = loc_tmp;
842  m_src_normals[i] = norm_tmp;
843  new_index_lookup[i] = idx_tmp;
844 
845  // Go next
846  prev_loc = m_locators[i];
847  }
848 
849  if (App::flexbody_defrag_invert_lookup->getBool())
850  {
851  std::vector<int> inverted_lookup(m_vertex_count);
852  for (int i = 0; i < (int)m_vertex_count; i++)
853  {
854  inverted_lookup[new_index_lookup[i]] = i;
855  }
856  for (int i = 0; i < (int)m_vertex_count; i++)
857  {
858  new_index_lookup[i] = inverted_lookup[i];
859  }
860  }
861 
862  // REORDERING VERTICES
863  // * positions/normals are calculated, no action needed.
864  // * texcoords (aka UV-coords) must be fixed.
866  {
867  Ogre::VertexData* vert_data = nullptr;
868  if (m_scene_entity->getMesh()->sharedVertexData)
869  {
870  vert_data = m_scene_entity->getMesh()->sharedVertexData;
871  }
872  else
873  {
874  // for simplicity we only support single submesh
875  vert_data = m_scene_entity->getMesh()->getSubMesh(0)->vertexData;
876  }
877  const Ogre::VertexElement* uv_elem = vert_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
878  Ogre::HardwareVertexBufferSharedPtr uv_buf = vert_data->vertexBufferBinding->getBuffer(uv_elem->getSource());
879  reorderVertexBuffer(uv_buf, uv_elem, new_index_lookup);
880  }
881 
882  // REORDERING INDICES
884  {
885  Ogre::IndexData* idx_data = m_scene_entity->getMesh()->getSubMesh(0)->indexData;
886  // Index can be 16-bit or 32-bit!
887  if (idx_data->indexBuffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT)
888  {
889  reorderIndexBuffer<uint16_t>(idx_data, new_index_lookup);
890  }
891  else
892  {
893  reorderIndexBuffer<uint32_t>(idx_data, new_index_lookup);
894  }
895  }
896 }
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
RoR::FlexBodyCacheData
Definition: FlexFactory.h:66
RoR::Locator_t::nx
NodeNum_t nx
Definition: Locator_t.h:13
RoR::FlexBody::reset
void reset()
Definition: FlexBody.cpp:692
RoR::FlexBody::destroyOgreObjects
void destroyOgreObjects()
Definition: FlexBody.cpp:572
RoR::FlexBody::FlexBody
FlexBody(RoR::FlexBodyCacheData *preloaded_from_cache, RoR::GfxActor *gfx_actor, Ogre::Entity *entity, NodeNum_t ref, NodeNum_t nx, NodeNum_t ny, Ogre::Vector3 offset, Ogre::Quaternion const &rot, std::vector< unsigned int > &node_indices, std::vector< ForvertTempData > &forvert_data)
Definition: FlexBody.cpp:38
RoR::FlexBodyCacheData::header
FlexBodyRecordHeader header
Definition: FlexFactory.h:77
RoR::Locator_t::ny
NodeNum_t ny
Definition: Locator_t.h:14
RoR::CAMERA_MODE_ALWAYS_HIDDEN
static CameraMode_t CAMERA_MODE_ALWAYS_HIDDEN
Definition: Application.h:564
RoR::FlexBody::m_scene_node
Ogre::SceneNode * m_scene_node
Definition: FlexBody.h:130
evalMemoryDistance
int evalMemoryDistance(Locator_t &a, Locator_t &b)
Definition: FlexBody.cpp:755
RoR::FlexBody::m_placeholder_type
PlaceholderType m_placeholder_type
Definition: FlexBody.h:118
RoR::FlexBody::PlaceholderType::NOT_A_PLACEHOLDER
@ NOT_A_PLACEHOLDER
RoR::NodeSB
Definition: SimBuffers.h:67
RoR::Locator_t::ref
NodeNum_t ref
Definition: Locator_t.h:12
RoR::Locator_t
Definition: Locator_t.h:10
RoR::FlexBody::m_forset_nodes
std::vector< NodeNum_t > m_forset_nodes
Definition: FlexBody.h:151
RoR::FlexBody::m_submesh_vbufs_vertex_counts
int m_submesh_vbufs_vertex_counts[16]
Definition: FlexBody.h:140
RoR::FlexBodyRecordHeader::HAS_TEXTURE
static const BitMask_t HAS_TEXTURE
Definition: FlexFactory.h:62
RoR::FlexBody::m_uses_shared_vertex_data
bool m_uses_shared_vertex_data
Definition: FlexBody.h:145
RoR::GfxActor::GetSimNodeBuffer
NodeSB * GetSimNodeBuffer()
Definition: GfxActor.h:129
RoR::FlexBody::updateFlexbodyVertexBuffers
void updateFlexbodyVertexBuffers()
Definition: FlexBody.cpp:661
RoR::FlexBodyRecordHeader::USES_SHARED_VERTEX_DATA
static const BitMask_t USES_SHARED_VERTEX_DATA
Definition: FlexFactory.h:61
RoR::FlexBody::m_orig_mesh_name
std::string m_orig_mesh_name
Definition: FlexBody.h:153
RoR::NODENUM_INVALID
static const NodeNum_t NODENUM_INVALID
Definition: ForwardDeclarations.h:55
format
Truck file format(technical spec)
RoR::FlexBody::defragmentFlexbodyMesh
void defragmentFlexbodyMesh()
Definition: FlexBody.cpp:793
RoR::FlexBody::m_shared_vbuf_pos
Ogre::HardwareVertexBufferSharedPtr m_shared_vbuf_pos
Definition: FlexBody.h:135
RoR::PrintMeshInfo
std::string PrintMeshInfo(std::string const &title, Ogre::MeshPtr mesh)
RoR::FlexBody::getForsetNodes
std::vector< NodeNum_t > & getForsetNodes()
Definition: FlexBody.h:98
RoR::Locator_t::is_forvert
bool is_forvert
Definition: Locator_t.h:16
RoR::FlexBodyRecordHeader::HAS_TEXTURE_BLEND
static const BitMask_t HAS_TEXTURE_BLEND
Definition: FlexFactory.h:63
RoR::NodeSB::nd_is_wet
bool nd_is_wet
Definition: SimBuffers.h:71
Console.h
RoR::FlexBody::setVisible
void setVisible(bool visible)
Definition: FlexBody.cpp:606
RoR::FlexBody::m_blend_changed
bool m_blend_changed
Definition: FlexBody.h:148
RoR::FlexBody::m_dst_pos
Ogre::Vector3 * m_dst_pos
Definition: FlexBody.h:120
RoR::FlexBody::m_dst_normals
Ogre::Vector3 * m_dst_normals
Definition: FlexBody.h:122
RoR::FlexBody::updateBlend
void updateBlend()
Definition: FlexBody.cpp:717
RoR::GfxScene::GetSceneManager
Ogre::SceneManager * GetSceneManager()
Definition: GfxScene.h:83
RoR::FlexBody::PlaceholderType::FAULTY_MESH_PLACEHOLDER
@ FAULTY_MESH_PLACEHOLDER
RoR::NodeSB::nd_has_contact
bool nd_has_contact
Definition: SimBuffers.h:70
RoR::FlexBody::m_has_texture
bool m_has_texture
Definition: FlexBody.h:146
RoR::FlexBody::m_camera_mode
int m_camera_mode
Visibility control {-2 = always, -1 = 3rdPerson only, 0+ = cinecam index}.
Definition: FlexBody.h:132
RoR::NodeNum_t
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
Definition: ForwardDeclarations.h:54
SimData.h
Core data structures for simulation; Everything affected by by either physics, network or user intera...
RoR::FlexBody::m_submesh_vbufs_color
Ogre::HardwareVertexBufferSharedPtr m_submesh_vbufs_color[16]
colors
Definition: FlexBody.h:143
RoR::FlexBody::PlaceholderType::FAULTY_FORSET_PLACEHOLDER
@ FAULTY_FORSET_PLACEHOLDER
RoR::FlexBody::~FlexBody
~FlexBody()
Definition: FlexBody.cpp:547
BITMASK_IS_1
#define BITMASK_IS_1(VAR, FLAGS)
Definition: BitFlags.h:14
RoR::FlexBody::m_src_colors
Ogre::ARGB * m_src_colors
Definition: FlexBody.h:123
RoR::FlexBody::m_shared_buf_num_verts
int m_shared_buf_num_verts
Definition: FlexBody.h:134
RoR::App::flexbody_defrag_reorder_indices
CVar * flexbody_defrag_reorder_indices
Definition: Application.cpp:269
GfxScene.h
RoR::FlexBody::m_num_submesh_vbufs
int m_num_submesh_vbufs
Definition: FlexBody.h:139
RoR::FlexBody::isVisible
bool isVisible() const
Definition: FlexBody.cpp:597
RoR::App::flexbody_defrag_reorder_texcoords
CVar * flexbody_defrag_reorder_texcoords
Definition: Application.cpp:270
fast_normalise
Ogre::Vector3 fast_normalise(Ogre::Vector3 v)
Definition: ApproxMath.h:151
Application.h
Central state/object manager and communications hub.
RoR::App::GetConsole
Console * GetConsole()
Definition: Application.cpp:286
RoR::FlexBody::PlaceholderType
PlaceholderType
Definition: FlexBody.h:63
FlexBody.h
RoR::Locator_t::getMean
NodeNum_t getMean()
Definition: Locator_t.h:20
ApproxMath.h
RoR::FlexBodyCacheData::src_normals
Ogre::Vector3 * src_normals
Definition: FlexFactory.h:80
RoR::App::flexbody_defrag_invert_lookup
CVar * flexbody_defrag_invert_lookup
Definition: Application.cpp:271
RoR::FlexBody::m_gfx_actor
RoR::GfxActor * m_gfx_actor
Definition: FlexBody.h:114
RoR::FlexBody::setFlexbodyCastShadow
void setFlexbodyCastShadow(bool val)
Definition: FlexBody.cpp:613
RoR::FlexBody::PlaceholderTypeToString
static const char * PlaceholderTypeToString(PlaceholderType type)
Definition: FlexBody.cpp:560
RoR::Locator_t::coords
Ogre::Vector3 coords
Definition: Locator_t.h:15
RoR::FlexBody::PlaceholderType::TUNING_REMOVED_PLACEHOLDER
@ TUNING_REMOVED_PLACEHOLDER
RoR::FlexBodyCacheData::src_colors
Ogre::ARGB * src_colors
Definition: FlexFactory.h:81
evalNodeDistance
int evalNodeDistance(NodeNum_t a, NodeNum_t b)
Definition: FlexBody.cpp:737
RoR::FlexBody::m_flexit_center
Ogre::Vector3 m_flexit_center
Updated per frame.
Definition: FlexBody.h:116
RoR::CVAR_TYPE_BOOL
@ CVAR_TYPE_BOOL
Definition: CVar.h:38
RoR::FlexBody::m_scene_entity
Ogre::Entity * m_scene_entity
Definition: FlexBody.h:131
nodes
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 On each side of there is max item Empty invalid string parses as node num items Acceptable item the node is the others When a node range has more than nodes
Definition: ReadMe.txt:302
RoR::FlexBodyRecordHeader::flags
BitMask_t flags
Definition: FlexFactory.h:58
reorderIndexBuffer
void reorderIndexBuffer(Ogre::IndexData *idx_data, std::vector< int > const &new_index_lookup)
Definition: FlexBody.cpp:765
RoR::FlexBody::m_locators
Locator_t * m_locators
1 loc per vertex
Definition: FlexBody.h:124
RoR::FlexBody::m_center_offset
Ogre::Vector3 m_center_offset
Definition: FlexBody.h:129
RoR::GfxActor
Definition: GfxActor.h:52
RoR::FlexBody::m_node_y
NodeNum_t m_node_y
Definition: FlexBody.h:128
Ogre
Definition: ExtinguishableFireAffector.cpp:35
GfxActor.h
Manager for all visuals belonging to a single actor.
RoR::FlexBody::m_src_normals
Ogre::Vector3 * m_src_normals
Definition: FlexBody.h:121
RoR::FlexBody::m_node_center
NodeNum_t m_node_center
Definition: FlexBody.h:126
RoR::FlexBody::m_has_texture_blend
bool m_has_texture_blend
Definition: FlexBody.h:147
RoR::CVar::getInt
int getInt() const
Definition: CVar.h:97
RoR::Locator_t::getSmallestNode
NodeNum_t getSmallestNode()
Definition: Locator_t.h:18
RoR::App::flexbody_defrag_prog_down_penalty
CVar * flexbody_defrag_prog_down_penalty
Definition: Application.cpp:268
RoR::FlexbodyID_t
int FlexbodyID_t
Index to GfxActor::m_flexbodies, use RoR::FLEXBODYID_INVALID as empty value.
Definition: ForwardDeclarations.h:64
RoR::FlexBodyRecordHeader::num_submesh_vbufs
int num_submesh_vbufs
Definition: FlexFactory.h:57
RoR::FlexBodyRecordHeader::vertex_count
int vertex_count
Definition: FlexFactory.h:50
FlexFactory.h
RoR::FlexBodyCacheData::locators
Locator_t * locators
1 loc per vertex
Definition: FlexFactory.h:82
RoR::FlexBody::m_id
FlexbodyID_t m_id
Definition: FlexBody.h:117
RoR::FlexBody::computeFlexbody
void computeFlexbody()
Updates mesh deformation; works on CPU using local copy of vertex data.
Definition: FlexBody.cpp:620
RoR::FlexBody::m_shared_vbuf_color
Ogre::HardwareVertexBufferSharedPtr m_shared_vbuf_color
Definition: FlexBody.h:137
RoR::FlexBody::m_submesh_vbufs_pos
Ogre::HardwareVertexBufferSharedPtr m_submesh_vbufs_pos[16]
positions
Definition: FlexBody.h:141
RoR::FlexBody::writeBlend
void writeBlend()
Definition: FlexBody.cpp:701
RoR::FlexBody::m_shared_vbuf_norm
Ogre::HardwareVertexBufferSharedPtr m_shared_vbuf_norm
Definition: FlexBody.h:136
RoR::FlexBodyCacheData::dst_pos
Ogre::Vector3 * dst_pos
Definition: FlexFactory.h:79
RoR::ForvertTempData
< Node resolution must be done in ActorSpawner, but vert resolution in FlexBody
Definition: Locator_t.h:23
RigDef_File.h
Data structures representing 'truck' file format, see https://docs.rigsofrods.org/vehicle-creation/fi...
RoR
Definition: AppContext.h:36
RoR::App::flexbody_defrag_const_penalty
CVar * flexbody_defrag_const_penalty
Definition: Application.cpp:266
RoR::App::GetGfxScene
GfxScene * GetGfxScene()
Definition: Application.cpp:292
RoR::FlexBody::m_submesh_vbufs_norm
Ogre::HardwareVertexBufferSharedPtr m_submesh_vbufs_norm[16]
normals
Definition: FlexBody.h:142
RoR::FlexBody::m_orig_mesh_info
std::string m_orig_mesh_info
Definition: FlexBody.h:152
RoR::FlexBody::m_node_x
NodeNum_t m_node_x
Definition: FlexBody.h:127
RoR::FlexBody::m_vertex_count
size_t m_vertex_count
Definition: FlexBody.h:115
reorderVertexBuffer
void reorderVertexBuffer(Ogre::HardwareVertexBufferSharedPtr vert_buf, const Ogre::VertexElement *vert_elem, std::vector< int > const &new_index_lookup)
Definition: FlexBody.cpp:777