76#include <OgreMaterialManager.h>
77#include <OgreSceneManager.h>
78#include <OgreMovableObject.h>
79#include <OgreParticleSystem.h>
80#include <OgreEntity.h>
82#include <fmt/format.h>
93 if (sectionconfig !=
"")
95 auto result = def->user_modules.find(sectionconfig);
97 if (result != def->user_modules.end())
100 LOG(
" == ActorSpawner: Module added to configuration: " + sectionconfig);
124 auto module = util.TransformToRigDefModule(addonpart_entry);
129 LOG(
" == ActorSpawner: Addon part added to configuration: " + addonpart);
150 App::GetCacheSystem()->LoadAssetPack(actor->getUsedActorEntry(), assetpack.filename);
166 for (
auto& def: module_def->
nodes)
219 req.
num_beams += wheel.num_rays * ((wheel.rigidity_node.IsValidAnyState()) ? 9 : 8);
228 req.
num_beams += wheel2.num_rays * ((wheel2.rigidity_node.IsValidAnyState()) ? 25 : 24);
235 req.
num_beams += meshwheel.num_rays * ((meshwheel.rigidity_node.IsValidAnyState()) ? 9 : 8);
239 req.
num_nodes += meshwheel2.num_rays * 2;
240 req.
num_beams += meshwheel2.num_rays * ((meshwheel2.rigidity_node.IsValidAnyState()) ? 9 : 8);
250 req.
num_beams += flexwheel.num_rays * ((flexwheel.rigidity_node.IsValidAnyState()) ? 21 : 20);
275 for (
size_t i = 0; i < req.
num_nodes; ++i)
341#ifdef USE_ANGELSCRIPT
411 "Failed to load built-in material 'tracks/simple'; disabling 'SimpleMaterials'");
481 float proped_wheels_radius_sum = 0.0f;
521 if ((a1 == i - 1) && (a2 == i - 0))
554 float max_dist = 0.0f;
568 float offset = atan2(dir.dotProduct(Ogre::Vector3::UNIT_Z), dir.dotProduct(Ogre::Vector3::UNIT_X));
588 Ogre::Vector3 cross = dir_node_offset.crossProduct(roll_node_offset);
642 if (wcent.x>prop.x && wcent.x<prop.x+15.0)
645 if (wcent.y>prop.y-radius && wcent.y<prop.y+radius)
650 float pleft=prop.z+radius;
651 float pright=prop.z-radius;
653 if (pleft<aleft) aleft=pleft;
655 if (pright>aright) aright=pright;
659 float wratio=(aleft-aright)/(wleft-wright);
683 Ogre::Entity* afterburn_ent =
nullptr;
693 propname, nozzle_ent, afterburn_ent);
717 return fmt::format(
"{}#{} ({} [Instance ID {}])",
722 return fmt::format(
"{} ({} [Instance ID {}])",
792 Ogre::String
const & airfoil,
801 this->
ComposeName(
"turboprop", aeroengine_index).c_str(),
830 if ((prop.pp_node_ref == ref_node_index) && (prop.pp_aero_propeller_blade || prop.pp_aero_propeller_spin))
832 prop.pp_scene_node->scale(scale, scale, scale);
833 prop.pp_aero_engine_idx = aeroengine_index;
890 this->
ComposeName(
"airbrake", airbrake_idx).c_str(),
921 ab->
offset = Ogre::Vector3::ZERO;
954 this->GetNodeIndexOrThrow(def.
nodes[2]),
955 this->GetNodeIndexOrThrow(def.
nodes[3]),
956 this->GetNodeIndexOrThrow(def.
nodes[4]),
957 this->GetNodeIndexOrThrow(def.
nodes[5]),
958 this->GetNodeIndexOrThrow(def.
nodes[6]),
959 this->GetNodeIndexOrThrow(def.
nodes[7]),
974 Ogre::Entity* entity =
nullptr;
1002 if (node1 != previous_wing.
fa->
nfld)
1037 left_green_prop.
pp_beacon_bbs[0]->setMaterialName(
"tracks/greenflare");
1041 left_green_prop.
pp_beacon_bbs[0]->setDefaultDimensions(0.5, 0.5);
1059 left_flash_prop.
pp_beacon_light[0]->setDiffuseColour( Ogre::ColourValue(1.0, 1.0, 1.0));
1060 left_flash_prop.
pp_beacon_light[0]->setSpecularColour( Ogre::ColourValue(1.0, 1.0, 1.0));
1061 left_flash_prop.
pp_beacon_light[0]->setAttenuation(50.0, 1.0, 0.3, 0.0);
1071 left_flash_prop.
pp_beacon_bbs[0]->setMaterialName(
"tracks/flare");
1075 left_flash_prop.
pp_beacon_bbs[0]->setDefaultDimensions(1.0, 1.0);
1100 right_red_prop.
pp_beacon_bbs[0]->setMaterialName(
"tracks/redflare");
1104 right_red_prop.
pp_beacon_bbs[0]->setDefaultDimensions(0.5, 0.5);
1122 right_flash_prop.
pp_beacon_light[0]->setDiffuseColour( Ogre::ColourValue(1.0, 1.0, 1.0));
1123 right_flash_prop.
pp_beacon_light[0]->setSpecularColour( Ogre::ColourValue(1.0, 1.0, 1.0));
1124 right_flash_prop.
pp_beacon_light[0]->setAttenuation(50.0, 1.0, 0.3, 0.0);
1134 right_flash_prop.
pp_beacon_bbs[0]->setMaterialName(
"tracks/flare");
1138 right_flash_prop.
pp_beacon_bbs[0]->setDefaultDimensions(1.0, 1.0);
1169 return (((
x-ref).crossProduct(
y-ref)).length()+((
x-aref).crossProduct(
y-aref)).length())*0.5f;
1203 if (sound_script ==
nullptr)
1228 auto itor = def.
nodes.begin();
1229 auto end = def.
nodes.end();
1230 for(; itor != end; ++itor)
1257 if (def.
key ==
"helpMaterial")
1261 else if (def.
key ==
"speedoMax")
1264 if (maxKph > 10 && maxKph < 32000)
1271 fmt::format(
"Invalid 'speedoMax' ({}), allowed range is <10 -32000>, using default ({})", maxKph,
DEFAULT_SPEEDO_MAX_KPH));
1275 else if (def.
key ==
"useMaxRPM")
1279 else if (def.
key ==
"shifterAnimTime")
1306 if (template_name ==
"" || template_name ==
"default")
1308 template_name =
"tracks/Smoke";
1316 if (exhaust.
smoker ==
nullptr)
1318 std::stringstream msg;
1319 msg <<
"Failed to create particle system '" << name <<
"' (template: '" << template_name <<
"')";
1339 for (; module_itor != module_end; ++module_itor)
1341 if (! module_itor->get()->submesh_groundmodel.empty())
1343 return module_itor->get()->submesh_groundmodel[0];
1346 return std::string();
1358 std::vector<RigDef::Texcoord>::iterator texcoord_itor = def.
texcoords.begin();
1359 for ( ; texcoord_itor != def.
texcoords.end(); texcoord_itor++)
1377 for ( ; cab_itor != cab_itor_end; ++cab_itor)
1385 std::stringstream msg;
1386 msg <<
"Collcab limit (" <<
MAX_CABS <<
") exceeded";
1391 bool mk_buoyance =
false;
1434 std::stringstream msg;
1435 msg <<
"Collcab limit (" <<
MAX_CABS <<
") exceeded";
1441 std::stringstream msg;
1442 msg <<
"Buoycab limit (" <<
MAX_CABS <<
") exceeded";
1544 std::vector<unsigned int> node_indices;
1545 bool nodes_found =
true;
1551 nodes_found =
false;
1554 node_indices.push_back(node);
1558 std::vector<ForvertTempData> forverts_tmp;
1559 for (
size_t i = 0; i < def.
forvert.size(); i++)
1561 const auto& forvert_item = def.
forvert[i];
1572 fmt::format(
"Flexbody {}({}) 'forvert'{}/{}: Some nodes not resolved (nref {}->{}, nx {}->{}, ny {}->{}).",
1581 forverts_tmp.push_back(fvtd);
1615 catch (Ogre::Exception&)
1638 pprop.
pp_id = prop_id;
1647 prop.
pp_id = prop_id;
1654 prop.
pp_rot = Ogre::Quaternion(Ogre::Degree(prop.
pp_rota.z), Ogre::Vector3::UNIT_Z)
1655 * Ogre::Quaternion(Ogre::Degree(prop.
pp_rota.y), Ogre::Vector3::UNIT_Y)
1656 * Ogre::Quaternion(Ogre::Degree(prop.
pp_rota.x), Ogre::Vector3::UNIT_X);
1676 Ogre::Vector3 steering_wheel_offset = Ogre::Vector3::ZERO;
1679 steering_wheel_offset = Ogre::Vector3(-0.67, -0.61,0.24);
1683 steering_wheel_offset = Ogre::Vector3(0.67, -0.61,0.24);
1685 if (steering_wheel_offset != Ogre::Vector3::ZERO)
1698 this->ComposeName(
"steering wheel entity @ prop", prop_id),
1710 this->ComposeName(
"prop entity", prop_id),
1759 pp_beacon_light->setType(Ogre::Light::LT_SPOTLIGHT);
1762 pp_beacon_light->setAttenuation(50.0, 1.0, 0.3, 0.0);
1763 pp_beacon_light->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) );
1764 pp_beacon_light->setCastShadows(
false);
1765 pp_beacon_light->setVisible(
false);
1770 if (flare_billboard_sys)
1772 flare_billboard_sys->createBillboard(0,0,0);
1773 flare_billboard_sys->setMaterialName(prop.
pp_media[1]);
1775 flare_scene_node->attachObject(flare_billboard_sys);
1777 flare_scene_node->setVisible(
false);
1791 pp_beacon_light->setType(Ogre::Light::LT_POINT);
1792 pp_beacon_light->setDiffuseColour( Ogre::ColourValue(1.0, 0.0, 0.0));
1793 pp_beacon_light->setSpecularColour( Ogre::ColourValue(1.0, 0.0, 0.0));
1794 pp_beacon_light->setAttenuation(50.0, 1.0, 0.3, 0.0);
1795 pp_beacon_light->setCastShadows(
false);
1796 pp_beacon_light->setVisible(
false);
1800 if (flare_billboard_sys)
1802 flare_billboard_sys->createBillboard(0,0,0);
1803 flare_billboard_sys->setMaterialName(
"tracks/redbeaconflare");
1805 flare_billboard_sys->setDefaultDimensions(1.0, 1.0);
1806 flare_scene_node->attachObject(flare_billboard_sys);
1808 flare_scene_node->setVisible(
false);
1820 for (
int k=0; k<4; k++)
1830 prop.
pp_beacon_light[k]->setDiffuseColour( Ogre::ColourValue(1.0, 0.0, 0.0));
1831 prop.
pp_beacon_light[k]->setSpecularColour( Ogre::ColourValue(1.0, 0.0, 0.0));
1835 prop.
pp_beacon_light[k]->setDiffuseColour( Ogre::ColourValue(0.0, 0.5, 1.0));
1836 prop.
pp_beacon_light[k]->setSpecularColour( Ogre::ColourValue(0.0, 0.5, 1.0));
1839 prop.
pp_beacon_light[k]->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) );
1850 prop.
pp_beacon_bbs[k]->setMaterialName(
"tracks/brightredflare");
1854 prop.
pp_beacon_bbs[k]->setMaterialName(
"tracks/brightblueflare");
1883 if (anim_def.ratio == 0)
1885 std::stringstream msg;
1886 msg <<
"Prop (mesh: " << def.
mesh_name <<
") has invalid animation ratio (0), using it anyway (compatibility)...";
2014 std::list<RigDef::Animation::MotorSource>::iterator source_itor = anim_def.motor_sources.begin();
2015 for ( ; source_itor != anim_def.motor_sources.end(); source_itor++)
2020 anim.
animOpt3 =
static_cast<float>(source_itor->motor);
2024 anim.
animOpt3 =
static_cast<float>(source_itor->motor);
2028 anim.
animOpt3 =
static_cast<float>(source_itor->motor);
2032 anim.
animOpt3 =
static_cast<float>(source_itor->motor);
2036 anim.
animOpt3 =
static_cast<float>(source_itor->motor);
2042 anim.
animOpt3 =
static_cast<float>(source_itor->motor);
2048 anim_def.event_name !=
"")
2067 anim_def.dash_link_name !=
"")
2077 anim.
animOpt3 =
static_cast<float>(link_id);
2115 const bool use_default_lower_limit = (anim_def.lower_limit == 0.f);
2116 const bool use_default_upper_limit = (anim_def.upper_limit == 0.f);
2119 anim.
lower_limit = (use_default_lower_limit) ? (-180.f) : (anim_def.lower_limit + prop.
pp_rota.x);
2120 anim.
upper_limit = (use_default_upper_limit) ? ( 180.f) : (anim_def.upper_limit + prop.
pp_rota.x);
2123 anim.
lower_limit = (use_default_lower_limit) ? (-180.f) : (anim_def.lower_limit + prop.
pp_rota.y);
2124 anim.
upper_limit = (use_default_upper_limit) ? ( 180.f) : (anim_def.upper_limit + prop.
pp_rota.y);
2127 anim.
lower_limit = (use_default_lower_limit) ? (-180.f) : (anim_def.lower_limit + prop.
pp_rota.z);
2128 anim.
upper_limit = (use_default_upper_limit) ? ( 180.f) : (anim_def.upper_limit + prop.
pp_rota.z);
2183 f.
bbs->setMaterial(f.
bbs->getMaterial()->clone(f.
snode->getName() +
"_mat"));
2192 float size = def.
size;
2197 if (blink_delay == -2)
2221 flare.
blinkdelay = (blink_delay == -1) ? 0.5f : blink_delay / 1000.f;
2243 fmt::format(
"Bad flare control num {}, must be 1-{}, using 1.",
2250 fmt::format(
"Bad flare control num {}, must be 1-{}, using {}.",
2266 fmt::format(
"Skipping 'd' flare, invalid input link '{}'", def.
dashboard_link));
2272 std::string flare_name = this->
ComposeName(
"Flare", flare_id);
2273 if (!is_placeholder)
2287 if (flare.
bbs ==
nullptr)
2293 flare.
bbs->createBillboard(0,0,0);
2296 if (using_default_material)
2300 material_name =
"tracks/brakeflare";
2304 material_name =
"tracks/blinkflare";
2308 material_name =
"tracks/greenflare";
2312 material_name =
"tracks/redflare";
2316 material_name =
"tracks/flare";
2323 flare.
bbs->setMaterial(material);
2324 flare.
snode->attachObject(flare.
bbs);
2328 flare.
light =
nullptr;
2335 flare.
light->setType(Ogre::Light::LT_SPOTLIGHT);
2336 flare.
light->setDiffuseColour( Ogre::ColourValue(1, 1, 1));
2337 flare.
light->setSpecularColour( Ogre::ColourValue(1, 1, 1));
2338 flare.
light->setAttenuation(200, 0.9, 0, 0);
2339 flare.
light->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) );
2340 flare.
light->setCastShadows(
false);
2345 flare.
light->setType(Ogre::Light::LT_SPOTLIGHT);
2346 flare.
light->setDiffuseColour(Ogre::ColourValue(1, 1, 1));
2347 flare.
light->setSpecularColour(Ogre::ColourValue(1, 1, 1));
2348 flare.
light->setAttenuation(400, 0.9, 0, 0);
2349 flare.
light->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(45));
2350 flare.
light->setCastShadows(
false);
2355 flare.
light->setType(Ogre::Light::LT_SPOTLIGHT);
2356 flare.
light->setDiffuseColour(Ogre::ColourValue(1, 1, 1));
2357 flare.
light->setSpecularColour(Ogre::ColourValue(1, 1, 1));
2358 flare.
light->setAttenuation(400, 0.9, 0, 0);
2359 flare.
light->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(45));
2360 flare.
light->setCastShadows(
false);
2368 flare.
light->setDiffuseColour( Ogre::ColourValue(1.0, 0, 0));
2369 flare.
light->setSpecularColour( Ogre::ColourValue(1.0, 0, 0));
2370 flare.
light->setAttenuation(10.0, 1.0, 0, 0);
2375 flare.
light->setDiffuseColour(Ogre::ColourValue(1, 1, 1));
2376 flare.
light->setSpecularColour(Ogre::ColourValue(1, 1, 1));
2377 flare.
light->setAttenuation(20.0, 1, 0, 0);
2382 flare.
light->setDiffuseColour( Ogre::ColourValue(1.0, 0, 0));
2383 flare.
light->setSpecularColour( Ogre::ColourValue(1.0, 0, 0));
2384 flare.
light->setAttenuation(10.0, 1.0, 0, 0);
2389 flare.
light->setDiffuseColour( Ogre::ColourValue(1, 1, 0));
2390 flare.
light->setSpecularColour( Ogre::ColourValue(1, 1, 0));
2391 flare.
light->setAttenuation(10.0, 1, 1, 0);
2396 flare.
light->setDiffuseColour( Ogre::ColourValue(1, 1, 1));
2397 flare.
light->setSpecularColour( Ogre::ColourValue(1, 1, 1));
2398 flare.
light->setAttenuation(1.0, 1.0, 1, 0.2);
2403 flare.
light->setDiffuseColour(Ogre::ColourValue(1, 1, 1));
2404 flare.
light->setSpecularColour(Ogre::ColourValue(1, 1, 1));
2405 flare.
light->setAttenuation(5.0, 1.0, 1, 0.2);
2410 if (flare.
light !=
nullptr)
2412 flare.
light->setType(Ogre::Light::LT_SPOTLIGHT);
2413 flare.
light->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) );
2414 flare.
light->setCastShadows(
false);
2421 LOG(fmt::format(
"[RoR|ActorSpawner] processing FlaregroupNoImport ({} {})", (
char)def.
type, def.
control_number));
2456 Ogre::MaterialPtr src_mat = Ogre::MaterialManager::getSingleton().getByName(source_name, rg_name);
2459 std::stringstream msg;
2460 msg <<
"Built-in material '" << source_name <<
"' missing! Skipping...";
2462 return Ogre::MaterialPtr();
2465 return src_mat->clone(clone_name);
2484 if (!Ogre::ResourceGroupManager::getSingleton().resourceExists(resource_group, def.
diffuse_map))
2491 !Ogre::ResourceGroupManager::getSingleton().resourceExists(resource_group, def.
damaged_diffuse_map))
2498 !Ogre::ResourceGroupManager::getSingleton().resourceExists(resource_group, def.
specular_map))
2510 std::string module_rg = (
module->origin_addonpart) ? module->origin_addonpart->resource_group : m_actor->getTruckFileResourceGroup();
2511 if (!Ogre::MaterialManager::getSingleton().getByName(def.
name, module_rg))
2513 LOG(fmt::format(
"[RoR] DBG ActorSpawner::ProcessManagedMaterial(): Creating placeholder for material '{}' in group '{}'", def.
name, module_rg));
2518 LOG(fmt::format(
"[RoR] DBG ActorSpawner::ProcessManagedMaterial(): Placeholder already exists: '{}' in group '{}'", def.
name, module_rg));
2523 Ogre::MaterialPtr material;
2527 material = Ogre::MaterialManager::getSingleton().getByName(
"tracks/transred")->clone(custom_name,
true, resource_group);
2531 std::string mat_name_base
2533 ?
"managed/flexmesh_standard"
2534 :
"managed/flexmesh_transparent";
2626 Ogre::String mat_name_base
2628 ?
"managed/mesh_standard"
2629 :
"managed/mesh_transparent";
2678 material->getTechnique(
"BaseTechnique")->getPass(
"BaseRender")->setCullingMode(Ogre::CULL_NONE);
2683 material->getTechnique(
"BaseTechnique")->getPass(
"SpecularMapping1")->setCullingMode(Ogre::CULL_NONE);
2687 material->getTechnique(
"BaseTechnique")->getPass(
"Specular")->setCullingMode(Ogre::CULL_NONE);
2693 material->compile();
2705 RoR::LogFormat(
"[RoR|Spawner] Collision box: skipping invalid node '%s'", node_ref.ToString().c_str());
2710 RoR::LogFormat(
"[RoR|Spawner] Collision box: re-assigning node '%s' from box ID '%d' to '%d'",
2711 node_ref.ToString().c_str(),
2739 _out_axle_wheel = i;
2762 std::stringstream msg;
2763 msg <<
"Couldn't find wheel with axis nodes '" << def.
wheels[0][0].
ToString()
2770 std::stringstream msg;
2771 msg <<
"Couldn't find wheel with axis nodes '" << def.
wheels[1][0].
ToString()
2785 for (
auto itor = def.
options.begin(); itor != end; ++itor)
2825 AddMessage(
Message::TYPE_ERROR,
"You cannot have both an inter-axle differential and a transfercase between the same two axles, skipping...");
2912 std::stringstream msg;
2914 <<
") must be positive nonzero number. Using it anyway (compatibility)";
2942 std::vector<RigDef::TorqueCurve::Sample>::iterator itor = def.
samples.begin();
2943 for ( ; itor != def.
samples.end(); itor++)
2945 target_torque_curve->
AddCurveSample(itor->power, itor->torque_percent);
2965 if (particle.
psys ==
nullptr)
2967 std::stringstream msg;
2968 msg <<
"Failed to create particle system '" << name <<
"' (template: '" << def.
particle_system_name <<
"')";
2974 particle.
snode->attachObject(particle.
psys);
3116 if (rail_group ==
nullptr)
3118 std::stringstream msg;
3119 msg <<
"Specified rail group id '" << def.
railgroup_id <<
"' not found. Ignoring slidenode...";
3127 if (rail_group !=
nullptr)
3142 std::vector<RigDef::Node::Range> & node_ranges,
3143 std::vector<NodeNum_t> & out_node_indices
3146 std::vector<RigDef::Node::Range>::iterator itor = node_ranges.begin();
3147 for ( ; itor != node_ranges.end(); itor++)
3149 if (itor->IsRange())
3161 std::stringstream msg;
3162 msg <<
"Encountered non-existent node '" << itor->end.ToString() <<
"' in range [" << itor->start.ToString() <<
" - " << itor->end.ToString() <<
"], "
3165 if (itor->end.Str().empty())
3167 msg <<
" However, this node must be accepted anyway for backwards compatibility."
3168 <<
" Please fix this as soon as possible.";
3169 end = itor->end.Num();
3186 for (
NodeNum_t i = start; i <= end; i++)
3188 out_node_indices.push_back(i);
3202 std::vector<NodeNum_t> node_indices;
3207 for (
unsigned int i = 0; i < node_indices.size() - 1; i++)
3210 if (beam ==
nullptr)
3212 std::stringstream msg;
3213 msg <<
"No beam between nodes indexed '" << node_indices[i] <<
"' and '" << node_indices[i + 1] <<
"'";
3223 for (
size_t i = 1; i < (num_seg - 1); ++i)
3230 const bool is_loop = (node_indices.front() == node_indices.back());
3267 if (node ==
nullptr)
3277 if (itor->hk_hook_node == node)
3284 if (hook ==
nullptr)
3286 std::stringstream msg;
3287 msg <<
"Node '" << def.
node.
ToString() <<
"' is not a hook-node (not marked with flag 'h'), ignoring...";
3318 int beam_index = -1;
3335 auto itor = lockgroup.
nodes.begin();
3336 auto end = lockgroup.
nodes.end();
3337 for (; itor != end; ++itor)
3350 bool invisible =
false;
3352 bool shock_trigger_enabled =
true;
3353 bool triggerblocker =
false;
3354 bool triggerblocker_inverted =
false;
3355 bool cmdkeyblock =
false;
3356 bool hooktoggle =
false;
3357 bool enginetrigger =
false;
3359 bool trigger_cmdkeyblock_state_short =
false;
3360 bool trigger_cmdkeyblock_state_long =
true;
3370 shock_trigger_enabled =
false;
3375 triggerblocker =
true;
3387 sbound = abs(sbound-1);
3393 triggerblocker_inverted =
true;
3412 enginetrigger =
true;
3415 if (!triggerblocker && !triggerblocker_inverted && !hooktoggle && !enginetrigger)
3424 else if (!hooktoggle && !enginetrigger)
3433 else if (enginetrigger)
3473 LOG(
"Trigger added. BeamID " +
TOSTRING(beam_index));
3477 beam.
shock = &shock;
3478 shock.
beamid = beam_index;
3480 if (!triggerblocker && !triggerblocker_inverted)
3490 if (!triggerblocker_inverted)
3506 if (cmdkeyblock && !triggerblocker)
3508 trigger_cmdkeyblock_state_short =
true;
3516 shock.
flags = shockflag;
3545 for (
unsigned int i = 0; i < 4; i++)
3581 for (
unsigned int i = 0; i < 4; i++)
3617 std::string start_function;
3618 std::string stop_function;
3645 Ogre::String start_function;
3646 Ogre::String stop_function;
3714 float center_length = 0.f;
3740 contract_command->
beams.push_back(cmd_beam);
3750 extend_command->
beams.push_back(cmd_beam);
3773 bool must_insert_qpair =
true;
3780 must_insert_qpair =
false;
3788 if (must_insert_qpair)
3801 float anim_option = 0;
3963 std::shared_ptr<RigDef::BeamDefaults> & beam_defaults,
3973 float strength = beam_defaults->breaking_threshold;
3979 float plastic_coef = beam_defaults->plastic_deform_coef;
3992 bool invisible =
false;
3993 unsigned int hydro_flags = 0;
4087 short_bound /= beam_length;
4088 long_bound /= beam_length;
4093 short_bound = (beam_length - short_bound) / beam_length;
4094 long_bound = (long_bound - beam_length) / beam_length;
4096 if (long_bound < 0.f)
4100 "Metric shock length calculation failed, 'short_bound' less than beams spawn length. Resetting to beam's spawn length (short_bound = 0)"
4105 if (short_bound > 1.f)
4109 "Metric shock length calculation failed, 'short_bound' less than 0 meters. Resetting to 0 meters (short_bound = 1)"
4140 shock.
flags = shock_flags;
4156 beam.
shock = & shock;
4157 shock.
beamid = beam_index;
4176 short_bound /= beam_length;
4177 long_bound /= beam_length;
4182 short_bound = (beam_length - short_bound) / beam_length;
4183 long_bound = (long_bound - beam_length) / beam_length;
4185 if (long_bound < 0.f)
4189 "Metric shock length calculation failed, 'short_bound' less than beams spawn length. Resetting to beam's spawn length (short_bound = 0)"
4194 if (short_bound > 1.f)
4198 "Metric shock length calculation failed, 'short_bound' less than 0 meters. Resetting to 0 meters (short_bound = 1)"
4229 shock.
flags = shock_flags;
4243 beam.
shock = & shock;
4244 shock.
beamid = beam_index;
4270 short_bound /= beam_length;
4271 long_bound /= beam_length;
4290 shock.
flags = shock_flags;
4305 beam.
shock = & shock;
4306 shock.
beamid = beam_index;
4320 node_t* swap = axis_node_1;
4321 axis_node_1 = axis_node_2;
4326 node_t *rigidity_node =
nullptr;
4327 node_t *axis_node_closest_to_rigidity_node =
nullptr;
4333 axis_node_closest_to_rigidity_node = ((distance_1 < distance_2)) ? axis_node_1 : axis_node_2;
4342 wheel.
wh_width = axis_vector.length();
4343 axis_vector.normalise();
4344 Ogre::Vector3 rim_ray_vector = axis_vector.perpendicular() * override_rim_radius;
4345 Ogre::Quaternion rim_ray_rotator = Ogre::Quaternion(Ogre::Degree(-360.f / (def.
num_rays * 2)), axis_vector);
4348 for (
unsigned int i = 0; i < def.
num_rays; i++)
4353 Ogre::Vector3 ray_point = axis_node_1->
RelPosition + rim_ray_vector;
4354 rim_ray_vector = rim_ray_rotator * rim_ray_vector;
4359 outer_node.
mass = node_mass;
4368 ray_point = axis_node_2->
RelPosition + rim_ray_vector;
4369 rim_ray_vector = rim_ray_rotator * rim_ray_vector;
4374 inner_node.
mass = node_mass;
4387 Ogre::Vector3 tyre_ray_vector = axis_vector.perpendicular() * override_tire_radius;
4388 Ogre::Quaternion& tyre_ray_rotator = rim_ray_rotator;
4389 tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector;
4392 for (
unsigned int i = 0; i < def.
num_rays; i++)
4396 Ogre::Vector3 ray_point = axis_node_1->
RelPosition + tyre_ray_vector;
4397 tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector;
4401 outer_node.
mass = node_mass;
4412 ray_point = axis_node_2->
RelPosition + tyre_ray_vector;
4413 tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector;
4417 inner_node.
mass = node_mass;
4428 wheel.
wh_nodes[i * 2] = & outer_node;
4429 wheel.
wh_nodes[(i * 2) + 1] = & inner_node;
4446 for (
unsigned int i = 0; i < def.
num_rays; i++)
4451 unsigned int rim_outer_node_index = base_node_index + (i * 2);
4461 unsigned int rim_next_outer_node_index = base_node_index + (((i + 1) % def.
num_rays) * 2);
4473 for (
unsigned int i = 0; i < def.
num_rays; i++)
4475 int rim_node_index = base_node_index + i*2;
4476 int tyre_node_index = base_node_index + i*2 + def.
num_rays*2;
4481 int tyre_base_index = (i == 0) ? tyre_node_index + (def.
num_rays * 2) : tyre_node_index;
4490 int index = (i == 0) ? tyre_node_index + (def.
num_rays * 2) - 1 : tyre_node_index - 1;
4499 int rimnode = rim_node_index;
4507 if (rigidity_node !=
nullptr)
4509 if (axis_node_closest_to_rigidity_node == axis_node_1)
4511 axis_node_closest_to_rigidity_node = &
m_actor->
ar_nodes[base_node_index+i*2+rays*2];
4514 axis_node_closest_to_rigidity_node = &
m_actor->
ar_nodes[base_node_index+i*2+1+rays*2];
4516 unsigned int beam_index =
AddWheelBeam(rigidity_node, axis_node_closest_to_rigidity_node, tyre_spring, tyre_damp, def.
beam_defaults);
4525 float support_beams_short_bound = 1.0f - ((override_rim_radius / override_tire_radius) * 0.95f);
4527 for (
unsigned int i=0; i<def.
num_rays; i++)
4530 unsigned int tirenode = base_node_index + i*2 + def.
num_rays*2;
4531 unsigned int beam_index;
4572 override_rim_radius,
4589 if (def_node_1 == def_node_2)
4591 throw Exception(
"Wheel axis nodes must not be set to single node!");
4597 out_node_1 = def_node_2;
4598 out_node_2 = def_node_1;
4602 out_node_1 = def_node_1;
4603 out_node_2 = def_node_2;
4611 node_t* axis_node_1 =
nullptr;
4612 node_t* axis_node_2 =
nullptr;
4677 node_t* axis_node_1 =
nullptr;
4678 node_t* axis_node_2 =
nullptr;
4714 float tyre_spring = def.
spring;
4715 float tyre_damp = def.
damping;
4757 unsigned int num_rays,
4759 Ogre::String mesh_name,
4760 Ogre::String mesh_rg,
4761 Ogre::String material_name,
4762 Ogre::String material_rg,
4793 catch (Ogre::Exception& e)
4802 unsigned int num_rays,
4805 node_t *reference_arm_node,
4806 unsigned int reserve_nodes,
4807 unsigned int reserve_beams,
4811 std::shared_ptr<RigDef::NodeDefaults> node_defaults,
4820 float axis_length = axis_vector.length();
4821 axis_vector.normalise();
4830 wheel.
wh_width = (wheel_width < 0) ? axis_length : wheel_width;
4846 Ogre::Vector3 ray_vector = axis_vector.perpendicular() * wheel_radius;
4847 Ogre::Quaternion ray_rotator = Ogre::Quaternion(Ogre::Degree(-360.0 / (num_rays * 2)), axis_vector);
4849 for (
unsigned int i = 0; i < num_rays; i++)
4852 Ogre::Vector3 ray_point = axis_node_1->
RelPosition + ray_vector;
4854 ray_vector = ray_rotator * ray_vector;
4857 InitNode(outer_node, ray_point, node_defaults);
4858 outer_node.
mass = wheel_mass / (2.f * num_rays);
4867 ray_point = axis_node_2->
RelPosition + ray_vector;
4869 ray_vector = ray_rotator * ray_vector;
4872 InitNode(inner_node, ray_point, node_defaults);
4873 inner_node.
mass = wheel_mass / (2.f * num_rays);
4882 wheel.
wh_nodes[i * 2] = & outer_node;
4883 wheel.
wh_nodes[(i * 2) + 1] = & inner_node;
4889 unsigned int options = (defaults->options | node_def.
options);
4899 unsigned int num_rays,
4907 std::shared_ptr<RigDef::BeamDefaults> beam_defaults,
4913 bool rigidity_beam_side_1 =
false;
4914 node_t *rigidity_node =
nullptr;
4920 rigidity_beam_side_1 = distance_1 < distance_2;
4923 for (
unsigned int i = 0; i < num_rays; i++)
4926 unsigned int outer_ring_node_index = base_node_index + (i * 2);
4930 AddWheelBeam(axis_node_1, outer_ring_node, tyre_spring, tyre_damping, beam_defaults, 0.66f, max_extension);
4931 AddWheelBeam(axis_node_2, inner_ring_node, tyre_spring, tyre_damping, beam_defaults, 0.66f, max_extension);
4932 AddWheelBeam(axis_node_2, outer_ring_node, tyre_spring, tyre_damping, beam_defaults);
4933 AddWheelBeam(axis_node_1, inner_ring_node, tyre_spring, tyre_damping, beam_defaults);
4936 unsigned int next_outer_ring_node_index = base_node_index + (((i + 1) % num_rays) * 2);
4940 AddWheelBeam(outer_ring_node, inner_ring_node, rim_spring, rim_damping, beam_defaults);
4941 AddWheelBeam(outer_ring_node, next_outer_ring_node, rim_spring, rim_damping, beam_defaults);
4942 AddWheelBeam(inner_ring_node, next_inner_ring_node, rim_spring, rim_damping, beam_defaults);
4943 AddWheelBeam(inner_ring_node, next_outer_ring_node, rim_spring, rim_damping, beam_defaults);
4946 if (rigidity_node !=
nullptr)
4948 node_t *target_node = (rigidity_beam_side_1) ? outer_ring_node : inner_ring_node;
4949 unsigned int beam_index =
AddWheelBeam(rigidity_node, target_node, tyre_spring, tyre_damping, beam_defaults, -1.f, -1.f,
BEAM_VIRTUAL);
4959 node_t* axis_node_1 =
nullptr;
4960 node_t* axis_node_2 =
nullptr;
5030 node_t* axis_node_1 =
nullptr;
5031 node_t* axis_node_2 =
nullptr;
5037 bool rigidity_beam_side_1 =
false;
5043 rigidity_beam_side_1 = distance_1 < distance_2;
5053 axis_vector.normalise();
5054 Ogre::Vector3 rim_ray_vector = Ogre::Vector3(0, override_rim_radius, 0);
5055 Ogre::Quaternion rim_ray_rotator = Ogre::Quaternion(Ogre::Degree(-360.f / wheel_2_def.
num_rays), axis_vector);
5058 wheel.
wh_width = axis_vector.length();
5061 for (
unsigned int i = 0; i < wheel_2_def.
num_rays; i++)
5063 float node_mass = wheel_2_def.
mass / (4.f * wheel_2_def.
num_rays);
5066 Ogre::Vector3 ray_point = axis_node_1->
RelPosition + rim_ray_vector;
5070 outer_node.
mass = node_mass;
5078 ray_point = axis_node_2->
RelPosition + rim_ray_vector;
5082 inner_node.
mass = node_mass;
5093 rim_ray_vector = rim_ray_rotator * rim_ray_vector;
5096 Ogre::Vector3 tyre_ray_vector = Ogre::Vector3(0, override_tire_radius, 0);
5097 Ogre::Quaternion tyre_ray_rotator = Ogre::Quaternion(Ogre::Degree(-180.f / wheel_2_def.
num_rays), axis_vector);
5098 tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector;
5101 for (
unsigned int i = 0; i < wheel_2_def.
num_rays; i++)
5104 Ogre::Vector3 ray_point = axis_node_1->
RelPosition + tyre_ray_vector;
5108 outer_node.
mass = (0.67f * wheel_2_def.
mass) / (2.f * wheel_2_def.
num_rays);
5118 ray_point = axis_node_2->
RelPosition + tyre_ray_vector;
5122 inner_node.
mass = (0.33f * wheel_2_def.
mass) / (2.f * wheel_2_def.
num_rays);
5132 wheel.
wh_nodes[i * 2] = & outer_node;
5133 wheel.
wh_nodes[(i * 2) + 1] = & inner_node;
5135 tyre_ray_vector = rim_ray_rotator * tyre_ray_vector;
5153 for (
unsigned int i = 0; i < wheel_2_def.
num_rays; i++)
5158 unsigned int rim_outer_node_index = base_node_index + (i * 2);
5162 unsigned int beam_index;
5163 beam_index =
AddWheelRimBeam(wheel_2_def, axis_node_1, rim_outer_node);
5165 beam_index =
AddWheelRimBeam(wheel_2_def, axis_node_2, rim_inner_node);
5171 unsigned int rim_next_outer_node_index = base_node_index + (((i + 1) % wheel_2_def.
num_rays) * 2);
5187 (rigidity_beam_side_1) ? rim_outer_node : rim_inner_node
5194 unsigned int tyre_node_index = rim_outer_node_index + (2 * wheel_2_def.
num_rays);
5197 unsigned int tyre_next_node_index = rim_next_outer_node_index + (2 * wheel_2_def.
num_rays);
5202 AddTyreBeam(wheel_2_def, tyre_outer_node, tyre_next_outer_node);
5203 AddTyreBeam(wheel_2_def, tyre_outer_node, tyre_next_inner_node);
5204 AddTyreBeam(wheel_2_def, tyre_inner_node, tyre_next_outer_node);
5205 AddTyreBeam(wheel_2_def, tyre_inner_node, tyre_next_inner_node);
5207 AddTyreBeam(wheel_2_def, tyre_outer_node, rim_outer_node);
5208 AddTyreBeam(wheel_2_def, tyre_outer_node, rim_next_outer_node);
5209 AddTyreBeam(wheel_2_def, tyre_inner_node, rim_inner_node);
5210 AddTyreBeam(wheel_2_def, tyre_inner_node, rim_next_inner_node);
5212 AddTyreBeam(wheel_2_def, tyre_outer_node, rim_inner_node);
5213 AddTyreBeam(wheel_2_def, tyre_outer_node, rim_next_inner_node);
5214 AddTyreBeam(wheel_2_def, tyre_inner_node, rim_outer_node);
5215 AddTyreBeam(wheel_2_def, tyre_inner_node, rim_next_outer_node);
5217 AddTyreBeam(wheel_2_def, axis_node_1, tyre_outer_node);
5218 AddTyreBeam(wheel_2_def, axis_node_2, tyre_inner_node);
5255 override_rim_radius / override_tire_radius
5264 unsigned int num_rays,
5265 Ogre::String
const& face_material_name,
5266 Ogre::String
const& face_material_rg,
5267 Ogre::String
const& band_material_name,
5268 Ogre::String
const& band_material_rg,
5281 const std::string wheel_mesh_name = this->
ComposeName(
"mesh @ wheel*", wheel_index);
5287 static_cast<NodeNum_t>(node_base_index),
5289 face_material_name, face_material_rg,
5290 band_material_name, band_material_rg,
5295 const std::string instance_name = this->
ComposeName(
"entity @ wheel*", wheel_index);
5303 catch (Ogre::Exception& e)
5317 std::string rim_mesh_name,
5318 std::string rim_mesh_rg,
5319 std::string tire_mesh_name,
5320 std::string tire_mesh_rg)
5338 int num_nodes = num_rays * 4;
5339 std::vector<unsigned int> node_indices;
5340 node_indices.reserve(num_nodes);
5341 for (
int i = 0; i < num_nodes; ++i)
5343 node_indices.push_back( node_base_index + i );
5345 std::vector<ForvertTempData> forverts;
5354 Ogre::Vector3(0.5f, 0.5f, 0.f),
5355 Ogre::Vector3(0.f, 0.f, 0.f),
5362 if (flexbody ==
nullptr)
5369 catch (Ogre::Exception& e)
5372 "Failed to create flexbodywheel visuals '" + tire_mesh_name +
"', reason:" + e.getDescription());
5381 std::shared_ptr<RigDef::BeamDefaults> beam_defaults,
5382 float max_contraction,
5383 float max_extension,
5392 if (max_contraction > 0.f)
5453 if (force < 1.f || force > 20.f)
5455 std::stringstream msg;
5456 msg <<
"Clamping 'regulating_force' value '" << force <<
"' to allowed range <1 - 20>";
5458 force = (force < 1.f) ? 1.f : 20.f;
5470 if (pulse <= 1.0f || pulse >= 2000.0f)
5486 if (force < 1.f || force > 20.f)
5488 std::stringstream msg;
5489 msg <<
"Clamping 'regulating_force' value '" << force <<
"' to allowed range <1 - 20>";
5491 force = (force < 1.f) ? 1.f : 20.f;
5502 if (pulse <= 1.0f || pulse >= 2000.0f)
5533 m_actor->
ar_engine->
SetTurboOptions(def.
version, def.
tinertiaFactor, def.
nturbos, def.
param1, def.
param2, def.
param3, def.
param4, def.
param5, def.
param6, def.
param7, def.
param8, def.
param9, def.
param10, def.
param11);
5610 std::stringstream msg;
5611 msg <<
"Failed to retrieve required node: " << node_ref.
ToString();
5653 beam.
k = def.
defaults->GetScaledSpringiness();
5654 beam.
d = def.
defaults->GetScaledDamping();
5662 float beam_strength = def.
defaults->GetScaledBreakingThreshold();
5785 if (beam_defaults->_is_user_defined)
5787 default_deform = beam_defaults->deformation_threshold;
5788 if (!beam_defaults->_enable_advanced_deformation && default_deform <
BEAM_DEFORM)
5793 if (beam_defaults->_is_plastic_deform_coef_user_defined && beam_defaults->plastic_deform_coef >=
BEAM_PLASTIC_COEF_DEFAULT)
5800 if (default_deform < beam_creak)
5802 default_deform = beam_creak;
5805 float deformation_threshold = default_deform * beam_defaults->scale.deformation_threshold_constant;
5814 std::string material_name = material_override;
5815 if (material_name.empty())
5819 material_name =
"tracks/Chrome";
5823 material_name = beam_defaults->beam_material_name;
5828 auto material = it->second;
5831 material_name = material->getName();
5845 entity->setMaterialName(material_name);
5848 beamx.
rod_diameter = beam_defaults->visual_beam_diameter;
5859 beamx.
rod_scenenode->setScale(beam_defaults->visual_beam_diameter, -1, beam_defaults->visual_beam_diameter);
5863 catch (Ogre::Exception& e)
5872 beam.
L = beam_length;
5873 beam.
refL = beam_length;
5896 txt <<
": " << text;
5926 bool is_imported = node_ref.GetImportState_IsValid();
5927 bool is_named = (is_imported ? node_ref.GetImportState_IsResolvedNamed() : node_ref.GetRegularState_IsNamed());
5936 std::stringstream msg;
5937 msg <<
"Failed to resolve node-ref (node not found):" << node_ref.
ToString();
5948 std::stringstream msg;
5974 if (node ==
nullptr)
5976 std::stringstream msg;
5977 msg <<
"Required node not found: " << node_ref.
ToString();
5987 std::stringstream msg;
5988 msg <<
"Attempt to add node with 'INVALID' flag: " <<
id.ToString() <<
" (number of nodes at this point: " <<
m_actor->
ar_num_nodes <<
")";
5993 if (
id.IsTypeNamed())
5996 auto insert_result =
m_named_nodes.insert(std::make_pair(
id.
Str(), new_index));
5997 if (! insert_result.second)
5999 std::stringstream msg;
6000 msg <<
"Ignoring named node! Duplicate name: " <<
id.Str() <<
" (number of nodes at this point: " <<
m_actor->
ar_num_nodes <<
")";
6010 if (
id.IsTypeNumbered())
6014 std::stringstream msg;
6015 msg <<
"Duplicate node number, previous definition will be overriden! - " <<
id.ToString() <<
" (number of nodes at this point: " <<
m_actor->
ar_num_nodes <<
")";
6024 throw Exception(
"Invalid Node::Id without type flags!");
6173 if (exhaust.
smoker ==
nullptr)
6181 exhaust.
smoker->setMaterialName(mat->getName(), mat->getGroup());
6213 for (
unsigned int i = 0; i < 8; i++)
6234 Ogre::Vector3
const & position,
6235 std::shared_ptr<RigDef::NodeDefaults> node_defaults
6252 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(def.
material_name);
6259 std::stringstream msg;
6260 msg <<
"Material '" << def.
material_name <<
"' defined in section 'globals' not found. Trying material 'tracks/transred'";
6276 std::stringstream msg;
6277 msg <<
"Axle limit (" <<
MAX_WHEELS/2 <<
") exceeded";
6288 std::stringstream msg;
6300 std::stringstream msg;
6313 std::stringstream msg;
6325 std::stringstream msg;
6326 msg <<
"Cab limit (" <<
MAX_CABS <<
") exceeded";
6337 std::stringstream msg;
6349 std::stringstream msg;
6361 std::stringstream msg;
6547 Ogre::String index_str =
TOSTRING(i+1);
6615 for (
auto& def:
module->materialflarebindings)
6617 if (def.material_name == material_name)
6630 for (
auto& def:
module->videocameras)
6632 if (def.material_name == material_name)
6650 return lookup_res->second.material;
6656 if (mat_lookup_name ==
"mirror")
6661 static int mirror_counter = 0;
6662 const std::string new_mat_name = this->
ComposeName(
"RenderMaterial", mirror_counter);
6664 lookup_entry.
material = Ogre::MaterialManager::getSingleton().getByName(
"mirror")->clone(new_mat_name,
true, mat_lookup_rg);
6672 if (videocam_def !=
nullptr)
6674 Ogre::MaterialPtr video_mat_shared;
6678 video_mat_shared = found_managedmat->second;
6682 video_mat_shared = Ogre::MaterialManager::getSingleton().getByName(mat_lookup_name);
6685 if (video_mat_shared)
6689 lookup_entry.
material = video_mat_shared->clone(video_mat_name,
true, mat_lookup_rg);
6695 std::stringstream msg;
6696 msg <<
"VideoCamera material '" << mat_lookup_name <<
"' not found! Ignoring videocamera.";
6703 if (mat_flare_def !=
nullptr)
6713 auto skin_res = skin_def->replace_materials.find(mat_lookup_name);
6714 if (skin_res != skin_def->replace_materials.end())
6716 Ogre::MaterialPtr skin_mat = Ogre::MaterialManager::getSingleton().getByName(
6720 lookup_entry.
material = skin_mat->clone(this->
ComposeName(skin_mat->getName()),
true, mat_lookup_rg);
6726 std::stringstream buf;
6730 <<
"')! Ignoring it...";
6741 lookup_entry.
material = mmat_res->second;
6746 Ogre::MaterialPtr orig_mat = Ogre::MaterialManager::getSingleton().getByName(mat_lookup_name, mat_lookup_rg);
6749 std::stringstream buf;
6750 buf <<
"Material doesn't exist:" << mat_lookup_name;
6752 return Ogre::MaterialPtr();
6755 lookup_entry.
material = orig_mat->clone(this->
ComposeName(orig_mat->getName()),
true, mat_lookup_rg);
6767 for (
auto& technique: lookup_entry.
material->getTechniques())
6769 for (
auto& pass: technique->getPasses())
6771 for (
auto& tex_unit: pass->getTextureUnitStates())
6774 if (tex_unit->getTextureName() ==
"dashtexture")
6779 std::stringstream msg;
6780 msg <<
"Warning: '" << mat_lookup_name
6781 <<
"' references 'dashtexture', but Renderdash isn't created yet! Texture will be blank.";
6792 const size_t num_frames = tex_unit->getNumFrames();
6793 for (
size_t i = 0; i < num_frames; ++i)
6802 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName(
6810 tex = Ogre::TextureManager::getSingleton().create(
6813 tex_unit->_setTexturePtr(tex, i);
6817 tex_unit->setFrameTextureName(query->second, (
unsigned int)i);
6829 catch (Ogre::Exception& e)
6831 std::stringstream msg;
6832 msg <<
"Exception while customizing material \"" << mat_lookup_name <<
"\", message: " << e.getFullDescription();
6835 return Ogre::MaterialPtr();
6842 static unsigned int simple_mat_counter = 0;
6844 newmat->getTechnique(0)->getPass(0)->setAmbient(color);
6880 size_t num_sub_entities = ent->getNumSubEntities();
6881 for (
size_t i = 0; i < num_sub_entities; i++)
6883 Ogre::SubEntity* subent = ent->getSubEntity(i);
6884 subent->setMaterial(mat);
6891 size_t subent_max = ent->getNumSubEntities();
6892 for (
size_t i = 0; i < subent_max; ++i)
6894 Ogre::SubEntity* subent = ent->getSubEntity(i);
6896 if (subent->getMaterial())
6901 subent->setMaterial(own_mat);
6915 if (entry.second.material_flare_def !=
nullptr)
6918 entry.second.material_flare_def->flare_number, entry.second.material);
6923 entry.second.material, entry.second.mirror_prop_type, entry.second.mirror_prop_scenenode);
6925 else if (entry.second.video_camera_def !=
nullptr)
6941 for (
auto& gs:
module->guisettings)
6943 if (gs.key == "dashboard")
6945 m_actor->ar_dashboard->loadDashBoard(gs.value, LOADDASHBOARD_SCREEN_HUD);
6947 else if (gs.key ==
"texturedashboard")
6958 switch (m_actor->ar_driveable)
6962 m_actor->ar_dashboard->setVisible(
false);
6966 m_actor->ar_dashboard->setVisible(
false);
6972 if (!m_help_material_name.empty())
6976 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(m_help_material_name, m_custom_resource_group);
6977 m_actor->m_gfx_actor->m_help_mat = mat;
6979 mat->getNumTechniques() > 0 &&
6980 mat->getTechnique(0)->getNumPasses() > 0 &&
6981 mat->getTechnique(0)->getPass(0)->getNumTextureUnitStates() > 0 &&
6982 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getNumFrames() > 0)
6984 m_actor->m_gfx_actor->m_help_tex =
6985 Ogre::TextureManager::getSingleton().getByName(
6986 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getFrameTextureName(0), m_custom_resource_group);
6989 catch (Ogre::Exception& e)
6991 this->AddMessage(Message::TYPE_ERROR,
6992 "Failed to load `help` material '" + m_help_material_name +
"', message:" + e.getFullDescription());
6996 m_actor->ar_managed_materials = m_managed_materials;
7001 const float eps = 0.001f;
7004 Ogre::Plane pl = Ogre::Plane((ax1 - ax2).normalisedCopy(), 0);
7010 float a1len = a1.normalise();
7011 float a2len = a2.normalise();
7012 float a3len = a3.normalise();
7013 float a4len = a4.normalise();
7014 if ((std::max(a1len, a3len) / std::min(a1len, a3len) > 1.f + eps) ||
7015 (std::max(a2len, a4len) / std::min(a2len, a4len) > 1.f + eps))
7017 Ogre::String msg = Ogre::StringUtil::format(
"Off-centered axis on base plate of rotator %d",
id);
7025 float b1len = b1.normalise();
7026 float b2len = b2.normalise();
7027 float b3len = b3.normalise();
7028 float b4len = b4.normalise();
7029 if ((std::max(b1len, b3len) / std::min(b1len, b3len) > 1.f + eps) ||
7030 (std::max(b2len, b4len) / std::min(b2len, b4len) > 1.f + eps))
7032 Ogre::String msg = Ogre::StringUtil::format(
"Off-centered axis on rotating plate of rotator %d",
id);
7036 float rot1 = a1.dotProduct(b1);
7037 float rot2 = a2.dotProduct(b2);
7038 float rot3 = a3.dotProduct(b3);
7039 float rot4 = a4.dotProduct(b4);
7040 if ((std::max(rot1, rot2) / std::min(rot1, rot2) > 1.f + eps) ||
7041 (std::max(rot2, rot3) / std::min(rot2, rot3) > 1.f + eps) ||
7042 (std::max(rot3, rot4) / std::min(rot3, rot4) > 1.f + eps) ||
7043 (std::max(rot4, rot1) / std::min(rot4, rot1) > 1.f + eps))
7045 Ogre::String msg = Ogre::StringUtil::format(
"Misaligned plates on rotator %d",
id);
7054 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(
7055 "VideoCamDebugMat-" +
TOSTRING(
counter), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
7057 mat->getTechnique(0)->getPass(0)->createTextureUnitState();
7058 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
7059 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureAnisotropy(3);
7060 mat->setLightingEnabled(
false);
7061 mat->setReceiveShadows(
false);
7064 mo->begin(mat->getName(), Ogre::RenderOperation::OT_LINE_LIST);
7065 Ogre::ColourValue pos_mark_col(1.f, 0.82f, 0.26f);
7066 Ogre::ColourValue dir_mark_col(0.f, 1.f, 1.f);
7067 const float pos_mark_len = 0.8f;
7068 const float dir_mark_len = 4.f;
7070 mo->position(pos_mark_len,0,0);
7071 mo->colour(pos_mark_col);
7072 mo->position(-pos_mark_len,0,0);
7073 mo->colour(pos_mark_col);
7075 mo->position(0,pos_mark_len,0);
7076 mo->colour(pos_mark_col);
7077 mo->position(0,-pos_mark_len,0);
7078 mo->colour(pos_mark_col);
7080 mo->position(0,0,pos_mark_len);
7081 mo->colour(pos_mark_col);
7082 mo->position(0,0,0);
7083 mo->colour(pos_mark_col);
7085 mo->position(0,0,-dir_mark_len);
7086 mo->colour(dir_mark_col);
7087 mo->position(0,0,0);
7088 mo->colour(dir_mark_col);
7122 float rotation_z = def->
rotation.z + 180;
7126 rotation_z += 180.0f;
7129 = Ogre::Quaternion(Ogre::Degree(rotation_z), Ogre::Vector3::UNIT_Z)
7130 * Ogre::Quaternion(Ogre::Degree(def->
rotation.y), Ogre::Vector3::UNIT_Y)
7131 * Ogre::Quaternion(Ogre::Degree(def->
rotation.x), Ogre::Vector3::UNIT_X);
7161 vcam.
vcam_render_tex = Ogre::TextureManager::getSingleton().createManual(
7163 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
7169 Ogre::TU_RENDERTARGET);
7188 vcam.
vcam_material->getTechnique(0)->getPass(0)->setLightingEnabled(
false);
7194 vp->setClearEveryFrame(
true);
7198 vp->setOverlaysEnabled(
false);
7204 vcam.
vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureUScale(-1);
7210 vp->setClearEveryFrame(
true);
7214 vp->setOverlaysEnabled(
false);
7228 catch (std::exception & ex)
7241 static int mprop_counter = 0;
7264 vcam.
vcam_render_tex = Ogre::TextureManager::getSingleton().createManual(
7265 this->
ComposeName(
"texture @ mirror", mprop_counter)
7272 , Ogre::TU_RENDERTARGET);
7286 v->setClearEveryFrame(
true);
7288 v->setOverlaysEnabled(
false);
7293 vcam.
vcam_material->getTechnique(0)->getPass(0)->setLightingEnabled(
false);
7298 catch (std::exception & ex)
7313 catch (Ogre::Exception& ogre_e)
7318 <<
") " << ogre_e.getFullDescription();
7322 catch (std::exception& std_e)
7337 Ogre::NameValuePairList params;
7339 params[
"templateName"] = template_name;
7342 name, Ogre::ParticleSystemFactory::FACTORY_TYPE_NAME, ¶ms);
7343 Ogre::ParticleSystem* psys =
static_cast<Ogre::ParticleSystem*
>(obj);
7347 for (
size_t i = 0; i < psys->getNumEmitters(); i++)
7349 psys->getEmitter(i)->setEnabled(
false);
7371 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(
m_cab_material_name);
7380 char transmatname[256];
7381 static int trans_counter = 0;
7383 Ogre::MaterialPtr transmat=mat->clone(transmatname);
7384 if (mat->getTechnique(0)->getNumPasses()>1)
7386 transmat->getTechnique(0)->removePass(1);
7388 transmat->getTechnique(0)->getPass(0)->setAlphaRejectSettings(Ogre::CMPF_LESS_EQUAL, 128);
7389 transmat->getTechnique(0)->getPass(0)->setDepthWriteEnabled(
false);
7390 if (transmat->getTechnique(0)->getPass(0)->getNumTextureUnitStates()>0)
7392 transmat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::TFO_NONE);
7394 transmat->compile();
7398 char backmatname[256];
7399 static int back_counter = 0;
7401 Ogre::MaterialPtr backmat=mat->clone(backmatname);
7402 if (mat->getTechnique(0)->getNumPasses()>1)
7404 backmat->getTechnique(0)->removePass(1);
7406 if (transmat->getTechnique(0)->getPass(0)->getNumTextureUnitStates()>0)
7408 backmat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx(
7412 Ogre::ColourValue(0,0,0),
7413 Ogre::ColourValue(0,0,0)
7418 backmat->setReceiveShadows(
false);
7424 char cab_material_name_cstr[1000] = {};
7426 std::string mesh_name = this->
ComposeName(
"mesh @ cab");
7434 cab_material_name_cstr,
7441 Ogre::Entity *ec =
nullptr;
7448 cab_scene_node->attachObject(ec);
7461 catch (Ogre::Exception& e)
7479 Ogre::Technique* tech = m->getTechnique(0);
7482 Ogre::Pass* p = tech->getPass(0);
7487 p->setSelfIllumination(Ogre::ColourValue::ZERO);
7517 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().load(
7523 tus->setTexture(tex);
Ogre::ManualObject * CreateVideocameraDebugMesh()
System integration layer; inspired by OgreBites::ApplicationContext.
Central state/object manager and communications hub.
#define ROR_ASSERT(_EXPR)
void LOG(const char *msg)
Legacy alias - formerly a macro.
#define BITMASK_SET_0(VAR, FLAGS)
#define BITMASK_IS_1(VAR, FLAGS)
#define BITMASK_IS_0(VAR, FLAGS)
#define BITMASK_SET_1(VAR, FLAGS)
A database of user-installed content alias 'mods' (vehicles, terrains...)
Game state manager and message-queue provider.
Manager for all visuals belonging to a single actor.
static const int MAX_CABS
maximum number of cabs per actor
static const int MAX_CLIGHTS
See RoRnet::Lightmask and enum events in InputEngine.h.
static const int MAX_CAMERAS
maximum number of cameras per actor
static const int MAX_AEROENGINES
maximum number of aero engines per actor
static const int MAX_WHEELS
maximum number of wheels per actor
static const int MAX_SUBMESHES
maximum number of submeshes per actor
static const int MAX_COMMANDS
maximum number of commands per actor
static const int MAX_SOUNDSCRIPTS_PER_TRUCK
maximum number of soundsscripts per actor
static const int MAX_TEXCOORDS
maximum number of texture coordinates per actor
static const int MAX_CAMERARAIL
maximum number of camera rail points
static const int MAX_SCREWPROPS
maximum number of boat screws per actor
#define SOUND_START(_ACTOR_, _TRIG_)
#define SOUND_MODULATE(_ACTOR_, _MOD_, _VALUE_)
void setCastShadows(bool b)
Ogre::SceneNode * GetSceneNode()
void setMaterialName(Ogre::String m)
Ogre::Entity * getEntity()
Abstract node ID (numbered or named) Node name is always available.
Legacy parser resolved references on-the-fly and the condition to check named nodes was "are there an...
bool IsValidAnyState() const
std::string ToString() const
std::string const & Str() const
bool alb_mode
Anti-lock brake state; Enabled? {1/0}.
float m_odometer_user
GUI state.
int m_num_command_beams
TODO: Remove! Spawner context only; likely unused feature.
float ar_collision_range
Physics attr.
std::vector< Ogre::AxisAlignedBox > ar_predicted_coll_bounding_boxes
std::vector< float > ar_minimass
minimum node mass in Kg - can be scaled in-game via NBUtil
TransferCase * m_transfer_case
Physics.
float ar_guisettings_speedo_max_kph
float ar_dry_mass
User-defined (editable via NBUtil); from 'globals' arg#1 - default for all nodes.
int ar_airbrake_intensity
Physics state; values 0-5.
int m_proped_wheel_pairs[MAX_WHEELS]
Physics attr; For inter-differential locking.
NodeNum_t ar_camera_node_dir[MAX_CAMERAS]
Physics attr; 'camera' = frame of reference; back node.
collcab_rate_t ar_intra_collcabrate[MAX_CABS]
std::vector< float > ar_nodes_override_loadweights
'nodes': 'l' flag and number.
std::vector< bool > ar_beams_invisible
Used only by the exporter (for rendering, invisible beams simply get no mesh).
std::vector< ropable_t > ar_ropables
CmdKeyArray ar_command_key
BEWARE: commandkeys are indexed 1-MAX_COMMANDS!
wheel_t ar_wheels[MAX_WHEELS]
std::vector< rope_t > ar_ropes
DashBoardManagerPtr ar_dashboard
float m_odometer_total
GUI state.
std::vector< wheeldetacher_t > ar_wheeldetachers
bool ar_camera_node_roll_inv[MAX_CAMERAS]
Physics attr; 'camera' = frame of reference; indicates roll node is right instead of left.
int ar_buoycabs[MAX_CABS]
std::vector< BitMask_t > ar_nodes_options
merged options from 'nodes' and 'set_node_defaults'
int m_num_wheel_diffs
Physics attr.
std::vector< bool > ar_beams_user_defined
True for 'beams', false for wheels/cinecam/hooknode/wings/rotators etc...
int m_num_proped_wheels
Physics attr, filled at spawn - Number of propelled wheels.
std::vector< Ogre::SceneNode * > m_deletion_scene_nodes
For unloading vehicle; filled at spawn.
std::vector< tie_t > ar_ties
int m_num_axle_diffs
Physics attr.
float ar_posnode_spawn_height
ground_model_t * ar_submesh_ground_model
std::vector< SlideNode > m_slidenodes
all the SlideNodes available on this actor
int * ar_nodes_id
Number in truck file, -1 for nodes generated by wheels/cinecam.
NodeNum_t ar_camera_node_roll[MAX_CAMERAS]
Physics attr; 'camera' = frame of reference; left node.
Differential * m_axle_diffs[1+MAX_WHEELS/2]
Physics.
ScrewpropPtr ar_screwprops[MAX_SCREWPROPS]
bool m_disable_smoke
Stops/starts smoke particles (i.e. exhausts, turbojets).
NodeNum_t ar_main_camera_node_pos
Sim attr; ar_camera_node_pos[0] >= 0 ? ar_camera_node_pos[0] : 0.
bool ar_is_police
Gfx/sfx attr.
std::vector< Airbrake * > ar_airbrakes
bool m_beam_break_debug_enabled
Logging state.
std::vector< float > ar_nodes_default_loadweights
'set_node_defaults': load weight.
NodeNum_t ar_camera_rail[MAX_CAMERARAIL]
Nodes defining camera-movement spline.
int ar_buoycab_types[MAX_CABS]
float m_fusealge_width
Physics attr; defined in truckfile.
Airfoil * m_fusealge_airfoil
Physics attr; defined in truckfile.
std::vector< Ogre::AxisAlignedBox > ar_collision_bounding_boxes
smart bounding boxes, used for determining the state of an actor (every box surrounds only a subset o...
soundsource_t ar_soundsources[MAX_SOUNDSCRIPTS_PER_TRUCK]
node_t * m_fusealge_front
Physics attr; defined in truckfile.
std::vector< flare_t > ar_flares
std::vector< Ogre::Entity * > m_deletion_entities
For unloading vehicle; filled at spawn.
std::unique_ptr< Buoyance > m_buoyance
bool alb_nodash
Anti-lock brake attribute: Hide the dashboard indicator?
bool sl_enabled
Speed limiter;.
ExtCameraMode ar_extern_camera_mode
float ar_load_mass
User-defined (editable via NBUtil); from 'globals' arg#2 - only applies to nodes with 'l' flag.
node_t * m_fusealge_back
Physics attr; defined in truckfile.
NodeNum_t ar_exhaust_dir_node
Old-format exhaust (one per vehicle) backwards direction node.
int ar_masscount
Calculated; Number of nodes loaded with l option.
PointColDetector * m_inter_point_col_detector
Physics.
BitMask_t m_flaregroups_no_import
RoRnet::Lightmask.
std::vector< RailGroup * > m_railgroups
all the available RailGroups for this actor
float m_handbrake_force
Physics attr; defined in truckfile.
NodeNum_t ar_extern_camera_node
Ogre::Vector3 ar_origin
Physics state; base position for softbody nodes.
float ar_guisettings_shifter_anim_time
float ar_brake_force
Physics attr; filled at spawn.
std::unique_ptr< GfxActor > m_gfx_actor
NodeNum_t ar_exhaust_pos_node
Old-format exhaust (one per vehicle) emitter node.
AeroEnginePtr ar_aeroengines[MAX_AEROENGINES]
std::string getTruckFileName()
int ar_num_shocks
Number of shock absorbers.
float ar_total_mass
Calculated; total mass in Kg.
float ar_anim_shift_timer
For 'animator' with flag 'shifter'.
float alb_ratio
Anti-lock brake attribute: Regulating force.
float cc_target_speed_lower_limit
Cruise Control.
std::vector< authorinfo_t > authors
bool m_beam_deform_debug_enabled
Logging state.
ActorInstanceID_t ar_instance_id
Static attr; session-unique ID.
bool alb_notoggle
Anti-lock brake attribute: Disable in-game toggle?
std::vector< PropAnimKeyState > m_prop_anim_key_states
bool m_has_axles_section
Temporary (legacy parsing helper) until central diffs are implemented.
bool ar_minimass_skip_loaded_nodes
std::string * ar_nodes_name
Name in truck file, only if defined with 'nodes2'.
float cc_target_rpm
Cruise Control.
NodeNum_t ar_camera_node_pos[MAX_CAMERAS]
Physics attr; 'camera' = frame of reference; origin node.
int ar_num_cinecams
Sim attr;.
GfxFlaresMode m_flares_mode
Snapshot of cvar 'gfx_flares_mode' on spawn.
collcab_rate_t ar_inter_collcabrate[MAX_CABS]
TyrePressure & getTyrePressure()
bool cc_mode
Cruise Control.
Differential * m_wheel_diffs[MAX_WHEELS/2]
Physics.
bool ar_hide_in_actor_list
Hide in list of spawned actors (available in top menubar). Useful for fixed-place machinery,...
float alb_pulse_time
Anti-lock brake attribute;.
Skidmark * m_skid_trails[MAX_WHEELS *2]
float alb_minspeed
Anti-lock brake attribute;.
Ogre::Quaternion ar_main_camera_dir_corr
Sim attr;.
bool m_has_command_beams
Physics attr;.
std::vector< std::string > m_description
VehicleAIPtr ar_vehicle_ai
float ar_anim_previous_crank
For 'animator' with flag 'torque'.
std::string getTruckFileResourceGroup()
bool tc_notoggle
Disable in-game toggle?
AutopilotPtr ar_autopilot
float tc_ratio
Regulating force.
float alb_timer
Anti-lock brake state;.
int ar_num_contacters
Total number of nodes which can selfcontact cabs.
std::vector< hydrobeam_t > ar_hydros
int ar_nodes_name_top_length
For nicely formatted diagnostic output.
NodeNum_t ar_main_camera_node_dir
Sim attr; ar_camera_node_dir[0] >= 0 ? ar_camera_node_dir[0] : 0.
std::vector< hook_t > ar_hooks
bool ar_collision_relevant
Physics state;.
PointColDetector * m_intra_point_col_detector
Physics.
CacheEntryPtr m_used_skin_entry
Optional, only graphics.
shock_t * ar_shocks
Shock absorbers.
bool tc_nodash
Hide the dashboard indicator?
NodeNum_t ar_cinecam_node[MAX_CAMERAS]
Sim attr; Cine-camera node indexes.
Ogre::Vector3 * ar_nodes_spawn_offsets
Relative positions (incl. Tuning system tweaks) from the definition file, for spawn-like resetting (i...
bool alb_pulse_state
Anti-lock brake state;.
CacheEntryPtrVec m_used_addonpart_entries
Optional, assigned by player via Tuning menu (.tuneup files).
float m_avg_proped_wheel_radius
Physics attr, filled at spawn - Average proped wheel radius.
bool m_trigger_debug_enabled
Logging state.
CacheEntryPtrVec m_used_assetpack_entries
Optional, specified by mod author in truck file via 'assetpacks' section.
int ar_collcabs[MAX_CABS]
bool ar_has_active_shocks
Are there active stabilizer shocks?
int ar_num_contactable_nodes
Total number of nodes which can contact ground or cabs.
TuneupDefPtr m_working_tuneup_def
Each actor gets unique instance, even if loaded from .tuneup file in modcache.
TuneupDefPtr & getWorkingTuneupDef()
bool ar_guisettings_use_engine_max_rpm
float cc_target_speed
Cruise Control.
float sl_speed_limit
Speed limiter;.
ActorType ar_driveable
Sim attr; marks vehicle type and features.
NodeNum_t ar_main_camera_node_roll
Sim attr; ar_camera_node_roll[0] >= 0 ? ar_camera_node_roll[0] : 0.
bool cc_can_brake
Cruise Control.
std::vector< UniqueCommandKeyPair > ar_unique_commandkey_pairs
UI helper for displaying command control keys to user (must be built at spawn).
RoR::CmdKeyInertiaConfig & GetInertiaConfig()
void ProcessAntiLockBrakes(RigDef::AntiLockBrakes &def)
std::map< std::string, Ogre::MaterialPtr > m_managed_materials
void CreateMeshWheelVisuals(WheelID_t wheel_id, NodeNum_t base_node_index, NodeNum_t axis_node_1_index, NodeNum_t axis_node_2_index, unsigned int num_rays, WheelSide side, Ogre::String mesh_name, Ogre::String mesh_rg, Ogre::String material_name, Ogre::String material_rg, float rim_radius)
static void AddSoundSource(ActorPtr const &vehicle, SoundScriptInstancePtr sound_script, NodeNum_t node_index, int type=-2)
void ConfigureAssetPacks(ActorPtr actor)
void ConfigureAddonParts(ActorPtr actor)
static bool CheckSoundScriptLimit(ActorPtr const &vehicle, unsigned int count)
void InitBeam(beam_t &beam, node_t *node_1, node_t *node_2)
void ProcessFlare2(RigDef::Flare2 &def)
RigDef::MaterialFlareBinding * FindFlareBindingForMaterial(std::string const &material_name)
Returns NULL if none found.
unsigned int AddTyreBeam(RigDef::Wheel2 &wheel_2_def, node_t *node_1, node_t *node_2)
std::list< std::shared_ptr< RigDef::Document::Module > > m_selected_modules
void ProcessScrewprop(RigDef::Screwprop &def)
bool CheckTexcoordLimit(unsigned int count)