diff --git a/source/main/Application.cpp b/source/main/Application.cpp index a94a48a804..bbd603fefb 100644 --- a/source/main/Application.cpp +++ b/source/main/Application.cpp @@ -150,6 +150,7 @@ CVar* diag_hide_wheels; CVar* diag_hide_nodes; CVar* diag_physics_dt; CVar* diag_terrn_log_roads; +CVar* diag_actor_dump; // Editing CVar* edi_import_grp_loose; diff --git a/source/main/Application.h b/source/main/Application.h index 9940cfec7c..d7d535fea9 100644 --- a/source/main/Application.h +++ b/source/main/Application.h @@ -317,6 +317,7 @@ extern CVar* diag_hide_wheels; extern CVar* diag_hide_nodes; extern CVar* diag_physics_dt; extern CVar* diag_terrn_log_roads; +extern CVar* diag_actor_dump; // Editing extern CVar* edi_import_grp_loose; diff --git a/source/main/physics/Actor.cpp b/source/main/physics/Actor.cpp index 699c5352ef..84c7f118cf 100644 --- a/source/main/physics/Actor.cpp +++ b/source/main/physics/Actor.cpp @@ -68,6 +68,9 @@ #include "VehicleAI.h" #include "Water.h" +#include +#include + using namespace Ogre; using namespace RoR; @@ -4575,3 +4578,63 @@ Vector3 Actor::getNodePosition(int nodeNumber) return Ogre::Vector3(); } } + +void Actor::WriteDiagnosticDump(std::string const& fileName) +{ + // Purpose: to diff against output from https://github.com/only-a-ptr/rigs-of-rods/tree/retro-0407 + std::stringstream buf; + + buf << "[nodes]" << std::endl; + for (int i = 0; i < ar_num_nodes; i++) + { + buf + << " pos:" << std::setw(3) << ar_nodes[i].pos // indicated pos in node buffer + << ((ar_nodes[i].pos != i) ? " !!sync " : "") // warn if the indicated pos doesn't match + << " (nodes)" + << " id:" << std::setw(3) << ar_nodes_id[i] + << " name:" << std::setw(ar_nodes_name_top_length) << ar_nodes_name[i] + << ", buoyancy:" << std::setw(8) << ar_nodes[i].buoyancy + << ", loaded:" << (int)(ar_nodes[i].nd_loaded_mass) + << " (wheels)" + << " wheel_rim:" << (int)ar_nodes[i].nd_rim_node + << ", wheel_tyre:" << (int)ar_nodes[i].nd_tyre_node + << " (set_node_defaults)" + << " mass:" << std::setw(8) << ar_nodes[i].mass // param 1 load weight + << ", friction_coef:" << std::setw(5) << ar_nodes[i].friction_coef // param 2 friction coef + << ", volume_coef:" << ar_nodes[i].volume_coef // param 3 volume coef + << ", surface_coef:" << ar_nodes[i].surface_coef // param 4 surface coef + << ", overrideMass:" << ar_nodes[i].nd_override_mass // depends on param 1 load weight + << " (contacters)" + << " " << ar_nodes[i].nd_contacter + << std::endl; + } + + buf << "[beams]" << std::endl; + for (int i = 0; i < ar_num_beams; i++) + { + buf + << " " << std::setw(4) << i // actual pos in beam buffer + << ", node1:" << std::setw(3) << ((ar_beams[i].p1) ? ar_nodes_id[ar_beams[i].p1->pos] : -1) + << ", node2:" << std::setw(3) << ((ar_beams[i].p2) ? ar_nodes_id[ar_beams[i].p2->pos] : -1) + << ", refLen:" << std::setw(9) << ar_beams[i].refL + << " (set_beam_defaults/scale)" + << " spring:" << std::setw(8) << ar_beams[i].k //param1 default_spring + << ", damp:" << std::setw(8) << ar_beams[i].d //param2 default_damp + << ", default_deform:" << std::setw(8) << ar_beams[i].default_beam_deform //param3 default_deform + << ", strength:" << std::setw(8) << ar_beams[i].strength //param4 default_break + //param5 default_beam_diameter ~ only visual + //param6 default_beam_material2 ~ only visual + << ", plastic_coef:" << std::setw(8) << ar_beams[i].plastic_coef //param7 default_plastic_coef + << std::endl; + } + + // Write out to 'logs' using OGRE resource system - complicated, but works with Unicode paths on Windows + Ogre::String rgName = "dumpRG"; + Ogre::ResourceGroupManager::getSingleton().addResourceLocation( + App::sys_logs_dir->GetStr(), "FileSystem", rgName, /*recursive=*/false, /*readOnly=*/false); + Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup(rgName); + Ogre::DataStreamPtr outStream = Ogre::ResourceGroupManager::getSingleton().createResource(fileName, rgName, /*overwrite=*/true); + std::string text = buf.str(); + outStream->write(text.c_str(), text.length()); + Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup(rgName); +} diff --git a/source/main/physics/Actor.h b/source/main/physics/Actor.h index 4f6d7e646e..aa21421031 100644 --- a/source/main/physics/Actor.h +++ b/source/main/physics/Actor.h @@ -154,6 +154,7 @@ class Actor : public ZeroedMemoryAllocator void updateSlideNodePositions(); //!< incrementally update the position of all SlideNodes void SoftReset(); void SyncReset(bool reset_position); //!< this one should be called only synchronously (without physics running in background) + void WriteDiagnosticDump(std::string const& filename); BlinkType getBlinkType(); std::vector getAuthors(); std::vector getDescription(); @@ -191,6 +192,9 @@ class Actor : public ZeroedMemoryAllocator // -------------------- Public data -------------------- // node_t* ar_nodes; + int* ar_nodes_id; //!< Number in truck file, -1 for nodes generated by wheels/cinecam + std::string* ar_nodes_name; //!< Name in truck file, only if defined with 'nodes2' + int ar_nodes_name_top_length = 0; //!< For nicely formatted diagnostic output int ar_num_nodes; beam_t* ar_beams; int ar_num_beams; diff --git a/source/main/physics/ActorManager.cpp b/source/main/physics/ActorManager.cpp index 5ca72484e7..5be3586288 100644 --- a/source/main/physics/ActorManager.cpp +++ b/source/main/physics/ActorManager.cpp @@ -332,6 +332,11 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, Truck::Documen } LOG(" ===== DONE LOADING VEHICLE"); + + if (App::diag_actor_dump->GetBool()) + { + actor->WriteDiagnosticDump(actor->ar_filename + "_dump.txt"); // Saves file to 'logs' + } } Actor* ActorManager::CreateActorInstance(ActorSpawnRequest rq, Truck::DocumentPtr def) diff --git a/source/main/physics/ActorSpawner.cpp b/source/main/physics/ActorSpawner.cpp index a44f67f9a6..347198a06b 100644 --- a/source/main/physics/ActorSpawner.cpp +++ b/source/main/physics/ActorSpawner.cpp @@ -152,7 +152,7 @@ void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements& req, Truck::M req.num_nodes += module_def->cinecam.size(); req.num_beams += module_def->cinecam.size() * 8; - // 'shocks' and 'shocks2' + // 'shocks', 'shocks2', 'shocks3' req.num_beams += module_def->shocks.size(); req.num_shocks += module_def->shocks.size(); req.num_beams += module_def->shocks_2.size(); @@ -221,6 +221,12 @@ void ActorSpawner::InitializeRig() // Allocate memory as needed m_actor->ar_beams = new beam_t[req.num_beams]; m_actor->ar_nodes = new node_t[req.num_nodes]; + m_actor->ar_nodes_id = new int[req.num_nodes]; + for (size_t i = 0; i < req.num_nodes; ++i) + { + m_actor->ar_nodes_id[i] = -1; + } + m_actor->ar_nodes_name = new std::string[req.num_nodes]; if (req.num_shocks > 0) m_actor->ar_shocks = new shock_t[req.num_shocks]; @@ -5529,6 +5535,9 @@ std::pair ActorSpawner::AddNode(Truck::Node::Id & id) this->AddMessage(Message::TYPE_ERROR, msg.str()); return std::make_pair(0, false); } + m_actor->ar_nodes_name[new_index] = id.Str(); + m_actor->ar_nodes_id[new_index] = m_actor->ar_num_nodes; + m_actor->ar_nodes_name_top_length = std::max(m_actor->ar_nodes_name_top_length, (int)id.Str().length()); m_actor->ar_num_nodes++; return std::make_pair(new_index, true); } @@ -5541,6 +5550,7 @@ std::pair ActorSpawner::AddNode(Truck::Node::Id & id) this->AddMessage(Message::TYPE_WARNING, msg.str()); } unsigned int new_index = static_cast(m_actor->ar_num_nodes); + m_actor->ar_nodes_id[new_index] = id.Num(); m_actor->ar_num_nodes++; return std::make_pair(new_index, true); } diff --git a/source/main/system/CVar.cpp b/source/main/system/CVar.cpp index b79daf2298..35d7eca5e9 100644 --- a/source/main/system/CVar.cpp +++ b/source/main/system/CVar.cpp @@ -96,6 +96,7 @@ void Console::CVarSetupBuiltins() App::diag_hide_nodes = this->CVarCreate("diag_hide_nodes", "Hide nodes", CVAR_ARCHIVE | CVAR_TYPE_BOOL, "false"); App::diag_physics_dt = this->CVarCreate("diag_physics_dt", "PhysicsTimeStep", CVAR_ARCHIVE | CVAR_TYPE_FLOAT, "0.0005"); App::diag_terrn_log_roads = this->CVarCreate("diag_terrn_log_roads", "", CVAR_ARCHIVE | CVAR_TYPE_BOOL, "false"); + App::diag_actor_dump = this->CVarCreate("diag_actor_dump", "", CVAR_ARCHIVE | CVAR_TYPE_BOOL, "false"); App::edi_import_grp_loose = this->CVarCreate("edi_import_grp_loose", "", CVAR_ARCHIVE | CVAR_TYPE_BOOL, "false"); App::edi_file_watch_respawn = this->CVarCreate("edi_file_watch_respawn", "", CVAR_ARCHIVE | CVAR_TYPE_BOOL, "false");