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
FlexFactory.cpp
Go to the documentation of this file.
1/*
2 This source file is part of Rigs of Rods
3
4 Copyright 2015-2020 Petr Ohlidal
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
24
25#include "FlexFactory.h"
26
27#include "Application.h"
28#include "Actor.h"
29#include "CacheSystem.h"
30#include "FlexBody.h"
31#include "FlexMeshWheel.h"
32#include "GfxScene.h"
33#include "PlatformUtils.h"
34#include "RigDef_File.h"
35#include "ActorSpawner.h"
36
37#include <OgreMeshManager.h>
38#include <OgreSceneManager.h>
39#include <MeshLodGenerator/OgreMeshLodGenerator.h>
40
41//#define FLEXFACTORY_DEBUG_LOGGING
42
43#ifdef FLEXFACTORY_DEBUG_LOGGING
44# include "RoRPrerequisites.h"
45# define FLEX_DEBUG_LOG(TEXT) LOG("FlexFactory | " TEXT)
46#else
47# define FLEX_DEBUG_LOG(TEXT)
48#endif // FLEXFACTORY_DEBUG_LOGGING
49
50using namespace RoR;
51
52// Static
53const char * FlexBodyFileIO::SIGNATURE = "RoR FlexBody";
54
56 m_rig_spawner(rig_spawner),
57 m_is_flexbody_cache_loaded(false),
58 m_is_flexbody_cache_enabled(App::gfx_flexbody_cache->getBool()),
59 m_flexbody_cache_next_index(0)
60{
61}
62
64 FlexbodyID_t flexbody_id,
65 const NodeNum_t ref_node,
66 const NodeNum_t x_node,
67 const NodeNum_t y_node,
68 Ogre::Vector3 offset,
69 Ogre::Vector3 rotation,
70 std::vector<unsigned int> & node_indices,
71 std::vector<ForvertTempData>& forvert_data,
72 const std::string& mesh_name,
73 const std::string& resource_group_name)
74{
75 Ogre::MeshPtr common_mesh = Ogre::MeshManager::getSingleton().load(mesh_name, resource_group_name);
76 const std::string mesh_unique_name = m_rig_spawner->ComposeName(fmt::format("{}_FlexBody", mesh_name).c_str(), flexbody_id);
77 Ogre::MeshPtr mesh = common_mesh->clone(mesh_unique_name);
78 const std::string flexbody_name = m_rig_spawner->ComposeName("Flexbody", flexbody_id);
79 Ogre::Entity* entity = App::GetGfxScene()->GetSceneManager()->createEntity(flexbody_name, mesh_unique_name, resource_group_name);
80 m_rig_spawner->SetupNewEntity(entity, Ogre::ColourValue(0.5, 0.5, 1));
81
82 FLEX_DEBUG_LOG(__FUNCTION__);
83 FlexBodyCacheData* from_cache = nullptr;
85 {
86 FLEX_DEBUG_LOG(__FUNCTION__ " >> Get entry from cache ");
89 }
90
91 Ogre::Quaternion rot=Ogre::Quaternion(Ogre::Degree(rotation.z), Ogre::Vector3::UNIT_Z);
92 rot=rot*Ogre::Quaternion(Ogre::Degree(rotation.y), Ogre::Vector3::UNIT_Y);
93 rot=rot*Ogre::Quaternion(Ogre::Degree(rotation.x), Ogre::Vector3::UNIT_X);
94
95 FlexBody* new_flexbody = new FlexBody(
96 from_cache,
98 entity,
99 ref_node,
100 x_node,
101 y_node,
102 offset,
103 rot,
104 node_indices,
105 forvert_data);
106
108 {
109 m_flexbody_cache.AddItemToSave(new_flexbody);
110 }
111 new_flexbody->m_id = flexbody_id;
112 new_flexbody->m_orig_mesh_name = common_mesh->getName();
113 return new_flexbody;
114}
115
117 unsigned int wheel_index,
118 int axis_node_1_index,
119 int axis_node_2_index,
120 int nstart,
121 int nrays,
122 float rim_radius,
123 bool rim_reverse,
124 std::string const & rim_mesh_name,
125 std::string const & rim_mesh_rg,
126 std::string const & tire_material_name,
127 std::string const & tire_material_rg)
128{
129 const ActorPtr& actor = m_rig_spawner->GetActor();
130
131 // Load+instantiate static mesh for rim (may be located in addonpart ZIP-bundle!)
132 const std::string rim_entity_name = m_rig_spawner->ComposeName("rim @ *wheel*", wheel_index);
133 Ogre::Entity* rim_prop_entity = App::GetGfxScene()->GetSceneManager()->createEntity(rim_entity_name, rim_mesh_name, rim_mesh_rg);
134 m_rig_spawner->SetupNewEntity(rim_prop_entity, Ogre::ColourValue(0, 0.5, 0.8));
135
136 // Create dynamic mesh for tire (always located in the actor resource group)
137 const std::string tire_mesh_name = m_rig_spawner->ComposeName("tire @ *wheel*", wheel_index);
138 FlexMeshWheel* flex_mesh_wheel = new FlexMeshWheel(
139 rim_prop_entity,
140 m_rig_spawner->m_wheels_parent_scenenode->createChildSceneNode(m_rig_spawner->ComposeName("*wheel*", wheel_index)), // Friend access
141 m_rig_spawner->GetActor()->GetGfxActor(), axis_node_1_index, axis_node_2_index, nstart, nrays,
142 tire_mesh_name, actor->GetGfxActor()->GetResourceGroup(),
143 tire_material_name, tire_material_rg, rim_radius, rim_reverse);
144
145 // Instantiate the dynamic tire mesh (always located in the actor resource group)
146 const std::string tire_instance_name = m_rig_spawner->ComposeName("tire entity @ *wheel*", wheel_index);
147 Ogre::Entity *tire_entity = App::GetGfxScene()->GetSceneManager()->createEntity(
148 tire_instance_name, tire_mesh_name, actor->GetGfxActor()->GetResourceGroup());
149 m_rig_spawner->SetupNewEntity(tire_entity, Ogre::ColourValue(0, 0.5, 0.8));
150 flex_mesh_wheel->m_tire_entity = tire_entity; // Friend access.
151
152 return flex_mesh_wheel;
153}
154
155void FlexBodyFileIO::WriteToFile(void* source, size_t length)
156{
157 size_t num_written = fwrite(source, length, 1, m_file);
158 if (num_written != 1)
159 {
160 FLEX_DEBUG_LOG(__FUNCTION__ " >> EXCEPTION!! ");
162 }
163}
164
165void FlexBodyFileIO::ReadFromFile(void* dest, size_t length)
166{
167 size_t num_written = fread(dest, length, 1, m_file);
168 if (num_written != 1)
169 {
170 FLEX_DEBUG_LOG(__FUNCTION__ " >> EXCEPTION!! ");
172 }
173}
174
176{
177 FLEX_DEBUG_LOG(__FUNCTION__);
178 WriteToFile((void*)SIGNATURE, (strlen(SIGNATURE) + 1) * sizeof(char));
179}
180
182{
183 FLEX_DEBUG_LOG(__FUNCTION__);
184 char signature[25];
185 this->ReadFromFile((void*)&signature, (strlen(SIGNATURE) + 1) * sizeof(char));
186 if (strcmp(SIGNATURE, signature) != 0)
187 {
189 }
190}
191
193{
194 FLEX_DEBUG_LOG(__FUNCTION__);
197 meta.num_flexbodies = static_cast<int>(m_items_to_save.size());
198
199 this->WriteToFile((void*)&meta, sizeof(FlexBodyFileMetadata));
200}
201
203{
204 FLEX_DEBUG_LOG(__FUNCTION__);
205 ROR_ASSERT(meta != nullptr);
206 this->ReadFromFile((void*)meta, sizeof(FlexBodyFileMetadata));
207}
208
210{
211 FLEX_DEBUG_LOG(__FUNCTION__);
213 header.vertex_count = static_cast<int>(flexbody->m_vertex_count);
214 header.node_center = flexbody->m_node_center ;
215 header.node_x = flexbody->m_node_x ;
216 header.node_y = flexbody->m_node_y ;
217 header.center_offset = flexbody->m_center_offset ;
218 header.camera_mode = flexbody->m_camera_mode ;
220 header.num_submesh_vbufs = flexbody->m_num_submesh_vbufs ;
221
225
226 this->WriteToFile((void*)&header, sizeof(FlexBodyRecordHeader));
227}
228
230{
231 FLEX_DEBUG_LOG(__FUNCTION__);
232 this->ReadFromFile((void*)&data->header, sizeof(FlexBodyRecordHeader));
233}
234
235
237{
238 FLEX_DEBUG_LOG(__FUNCTION__);
239 this->WriteToFile((void*)flexbody->m_locators, sizeof(Locator_t) * flexbody->m_vertex_count);
240}
241
243{
244 FLEX_DEBUG_LOG(__FUNCTION__);
245 // Alloc. Use <new> - experiment
246 data->locators = new Locator_t[data->header.vertex_count];
247 // Read
248 this->ReadFromFile((void*)data->locators, sizeof(Locator_t) * data->header.vertex_count);
249}
250
252{
253 FLEX_DEBUG_LOG(__FUNCTION__);
254 this->WriteToFile((void*)flexbody->m_src_normals, sizeof(Ogre::Vector3) * flexbody->m_vertex_count);
255}
256
258{
259 FLEX_DEBUG_LOG(__FUNCTION__);
260 const int vertex_count = data->header.vertex_count;
261 // Alloc. Use malloc() because that's how flexbodies were implemented.
262 data->src_normals=(Ogre::Vector3*)malloc(sizeof(Ogre::Vector3) * vertex_count);
263 // Read
264 this->ReadFromFile((void*)data->src_normals, sizeof(Ogre::Vector3) * vertex_count);
265}
266
268{
269 FLEX_DEBUG_LOG(__FUNCTION__);
270 this->WriteToFile((void*)flexbody->m_dst_pos, sizeof(Ogre::Vector3) * flexbody->m_vertex_count);
271}
272
274{
275 FLEX_DEBUG_LOG(__FUNCTION__);
276 const int vertex_count = data->header.vertex_count;
277 // Alloc. Use malloc() because that's how flexbodies were implemented.
278 data->dst_pos=(Ogre::Vector3*)malloc(sizeof(Ogre::Vector3) * vertex_count);
279 // Read
280 this->ReadFromFile((void*)data->dst_pos, sizeof(Ogre::Vector3) * vertex_count);
281}
282
284{
285 FLEX_DEBUG_LOG(__FUNCTION__);
286 if (flexbody->m_has_texture_blend)
287 {
288 this->WriteToFile((void*)flexbody->m_src_colors, sizeof(Ogre::ARGB) * flexbody->m_vertex_count);
289 }
290}
291
293{
294 FLEX_DEBUG_LOG(__FUNCTION__);
296 {
297 return;
298 }
299 const int vertex_count = data->header.vertex_count;
300 // Alloc. Use malloc() because that's how flexbodies were implemented.
301 data->src_colors=(Ogre::ARGB*)malloc(sizeof(Ogre::ARGB) * vertex_count);
302 // Read
303 this->ReadFromFile((void*)data->src_colors, sizeof(Ogre::ARGB) * vertex_count);
304}
305
306void FlexBodyFileIO::OpenFile(const char* fopen_mode)
307{
308 FLEX_DEBUG_LOG(__FUNCTION__);
309 if (m_cache_entry_number == -1)
310 {
312 }
313 char path[500];
314 sprintf(path, "%s%cflexbodies_mod_%00d.dat", App::sys_cache_dir->getStr().c_str(), RoR::PATH_SLASH, m_cache_entry_number);
315 m_file = fopen(path, fopen_mode);
316 if (m_file == nullptr)
317 {
319 }
320}
321
323{
324 FLEX_DEBUG_LOG(__FUNCTION__);
325 if (m_items_to_save.size() == 0)
326 {
327 FLEX_DEBUG_LOG(__FUNCTION__ " >> No flexbodies to save >> EXIT");
328 return RESULT_CODE_OK;
329 }
330 try
331 {
332 this->OpenFile("wb");
333
334 this->WriteSignature();
335 this->WriteMetadata();
336
337 auto itor = m_items_to_save.begin();
338 auto end = m_items_to_save.end();
339 for (; itor != end; ++itor)
340 {
341 FlexBody* flexbody = *itor;
342 this->WriteFlexbodyHeader(flexbody);
343
344 this->WriteFlexbodyLocatorList (flexbody);
345 this->WriteFlexbodyPositionsBuffer(flexbody);
346 this->WriteFlexbodyNormalsBuffer (flexbody);
347 this->WriteFlexbodyColorsBuffer (flexbody);
348 }
349 this->CloseFile();
350 FLEX_DEBUG_LOG(__FUNCTION__ " >> OK ");
351 return RESULT_CODE_OK;
352 }
353 catch (ResultCode result)
354 {
355 this->CloseFile();
356 FLEX_DEBUG_LOG(__FUNCTION__ " >> EXCEPTION!! ");
357 return result;
358 }
359}
360
362{
363 FLEX_DEBUG_LOG(__FUNCTION__);
364 try
365 {
366 this->OpenFile("rb");
367 this->ReadAndCheckSignature();
368
370 this->ReadMetadata(&meta);
373 {
375 }
376 m_loaded_items.resize(meta.num_flexbodies);
377
378 for (unsigned int i = 0; i < meta.num_flexbodies; ++i)
379 {
381 this->ReadFlexbodyHeader(data);
383 {
384 this->ReadFlexbodyLocatorList (data);
385 this->ReadFlexbodyPositionsBuffer(data);
386 this->ReadFlexbodyNormalsBuffer (data);
387 this->ReadFlexbodyColorsBuffer (data);
388 }
389 }
390
391 this->CloseFile();
392 FLEX_DEBUG_LOG(__FUNCTION__ " >> OK ");
393 return RESULT_CODE_OK;
394 }
395 catch (ResultCode ret)
396 {
397 this->CloseFile();
398 FLEX_DEBUG_LOG(__FUNCTION__ " >> EXCEPTION!! ");
399 return ret;
400 }
401}
402
404 m_file(nullptr),
405 m_fileformat_version(0),
406 m_cache_entry_number(-1) // flexbody cache disabled (shouldn't be based on the cache entry number ...) ~ ulteq 01/19
407 {}
408
418
420{
421 FLEX_DEBUG_LOG(__FUNCTION__);
423 {
424 FLEX_DEBUG_LOG(__FUNCTION__ " >> Saving flexbodies");
426 }
427}
428
Vehicle spawning logic.
Central state/object manager and communications hub.
#define ROR_ASSERT(_EXPR)
Definition Application.h:40
#define BITMASK_IS_0(VAR, FLAGS)
Definition BitFlags.h:13
#define BITMASK_SET_1(VAR, FLAGS)
Definition BitFlags.h:17
A database of user-installed content alias 'mods' (vehicles, terrains...)
#define FLEX_DEBUG_LOG(TEXT)
Platform-specific utilities. We use narrow UTF-8 encoded strings as paths. Inspired by http://utf8eve...
Data structures representing 'truck' file format, see https://docs.rigsofrods.org/vehicle-creation/fi...
GfxActor * GetGfxActor()
Definition Actor.h:309
Processes a RigDef::Document (parsed from 'truck' file format) into a simulated gameplay object (Acto...
ActorPtr GetActor()
void SetupNewEntity(Ogre::Entity *e, Ogre::ColourValue simple_color)
Full texture and material setup.
Ogre::SceneNode * m_wheels_parent_scenenode
this isn't used for moving/hiding things, just helps developers inspect the scene graph.
std::string ComposeName(const std::string &object, int number=-1)
Creates name containing actor ID token, i.e. "Object#1 (filename.truck [Instance ID 1])".
void ReadFlexbodyColorsBuffer(FlexBodyCacheData *flexbody)
void WriteFlexbodyNormalsBuffer(FlexBody *flexbody)
void ReadFlexbodyPositionsBuffer(FlexBodyCacheData *flexbody)
void OpenFile(const char *fopen_mode)
ResultCode LoadFile()
FlexBodyCacheData * GetLoadedItem(unsigned index)
unsigned int m_fileformat_version
void ReadFromFile(void *dest, size_t length)
void WriteToFile(void *source, size_t length)
void WriteFlexbodyHeader(FlexBody *flexbody)
void WriteFlexbodyLocatorList(FlexBody *flexbody)
void ReadFlexbodyNormalsBuffer(FlexBodyCacheData *flexbody)
void ReadFlexbodyHeader(FlexBodyCacheData *flexbody)
void AddItemToSave(FlexBody *fb)
void WriteFlexbodyColorsBuffer(FlexBody *flexbody)
ResultCode SaveFile()
void ReadFlexbodyLocatorList(FlexBodyCacheData *flexbody)
@ RESULT_CODE_ERR_CACHE_NUMBER_UNDEFINED
void WriteFlexbodyPositionsBuffer(FlexBody *flexbody)
std::vector< FlexBodyCacheData > m_loaded_items
void ReadMetadata(FlexBodyFileMetadata *meta)
static const unsigned int FILE_FORMAT_VERSION
static const char * SIGNATURE
std::vector< FlexBody * > m_items_to_save
Flexbody = A deformable mesh; updated on CPU every frame, then uploaded to video memory.
Definition FlexBody.h:44
std::string m_orig_mesh_name
Definition FlexBody.h:153
Ogre::ARGB * m_src_colors
Definition FlexBody.h:123
Locator_t * m_locators
1 loc per vertex
Definition FlexBody.h:124
NodeNum_t m_node_y
Definition FlexBody.h:128
int m_num_submesh_vbufs
Definition FlexBody.h:139
Ogre::Vector3 m_center_offset
Definition FlexBody.h:129
NodeNum_t m_node_center
Definition FlexBody.h:126
bool m_has_texture
Definition FlexBody.h:146
size_t m_vertex_count
Definition FlexBody.h:115
int m_camera_mode
Visibility control {-2 = always, -1 = 3rdPerson only, 0+ = cinecam index}.
Definition FlexBody.h:132
FlexbodyID_t m_id
Definition FlexBody.h:117
bool m_has_texture_blend
Definition FlexBody.h:147
Ogre::Vector3 * m_dst_pos
Definition FlexBody.h:120
int m_shared_buf_num_verts
Definition FlexBody.h:134
Ogre::Vector3 * m_src_normals
Definition FlexBody.h:121
bool m_uses_shared_vertex_data
Definition FlexBody.h:145
NodeNum_t m_node_x
Definition FlexBody.h:127
FlexMeshWheel * CreateFlexMeshWheel(unsigned int wheel_index, int axis_node_1_index, int axis_node_2_index, int nstart, int nrays, float rim_radius, bool rim_reverse, std::string const &rim_mesh_name, std::string const &rim_mesh_rg, std::string const &tire_material_name, std::string const &tire_material_rg)
bool m_is_flexbody_cache_loaded
void SaveFlexbodiesToCache()
FlexBodyFileIO m_flexbody_cache
FlexBody * CreateFlexBody(FlexbodyID_t flexbody_id, const NodeNum_t ref_node, const NodeNum_t x_node, const NodeNum_t y_node, Ogre::Vector3 offset, Ogre::Vector3 rotation, std::vector< unsigned int > &node_indices, std::vector< ForvertTempData > &forvert_data, const std::string &mesh_name, const std::string &resource_group_name)
unsigned int m_flexbody_cache_next_index
void CheckAndLoadFlexbodyCache()
ActorSpawner * m_rig_spawner
bool m_is_flexbody_cache_enabled
Consists of static mesh, representing the rim, and dynamic mesh, representing the tire.
Ogre::Entity * m_tire_entity
Ogre::String GetResourceGroup()
Definition GfxActor.h:146
Ogre::SceneManager * GetSceneManager()
Definition GfxScene.h:83
char PATH_SLASH
GfxScene * GetGfxScene()
CVar * sys_cache_dir
int FlexbodyID_t
Index to GfxActor::m_flexbodies, use RoR::FLEXBODYID_INVALID as empty value.
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
Ogre::Vector3 * dst_pos
Definition FlexFactory.h:79
Ogre::ARGB * src_colors
Definition FlexFactory.h:81
Ogre::Vector3 * src_normals
Definition FlexFactory.h:80
FlexBodyRecordHeader header
Definition FlexFactory.h:77
Locator_t * locators
1 loc per vertex
Definition FlexFactory.h:82
static const BitMask_t HAS_TEXTURE_BLEND
Definition FlexFactory.h:63
Ogre::Vector3 center_offset
Definition FlexFactory.h:54
static const BitMask_t HAS_TEXTURE
Definition FlexFactory.h:62
static const BitMask_t IS_FAULTY
Definition FlexFactory.h:60
static const BitMask_t USES_SHARED_VERTEX_DATA
Definition FlexFactory.h:61