46 void Actor::CalcForcesEulerCompute(
bool doUpdate,
int num_steps)
49 this->UpdateBoundingBoxes();
50 this->CalcEventBoxes();
52 this->CalcAircraftForces(doUpdate);
54 this->CalcBuoyance(doUpdate);
55 this->CalcDifferentials();
56 this->CalcWheels(doUpdate, num_steps);
57 this->CalcShocks(doUpdate, num_steps);
59 this->CalcCommands(doUpdate);
61 this->CalcTruckEngine(doUpdate);
63 this->CalcBeams(doUpdate);
64 this->CalcCabCollisions();
66 this->CalcForceFeedback(doUpdate);
69 void Actor::CalcForceFeedback(
bool doUpdate)
75 m_force_sensors.Reset();
78 if (ar_current_cinecam != -1)
80 m_force_sensors.accu_body_forces += ar_nodes[ar_camera_node_pos[ar_current_cinecam]].Forces;
85 beam_t* beam = &ar_beams[hydrobeam.hb_beam_index];
88 m_force_sensors.accu_hydros_forces += hydrobeam.hb_speed * beam->
refL * beam->
stress;
94 void Actor::CalcMouse()
98 Vector3 dir = m_mouse_grab_pos - ar_nodes[m_mouse_grab_node].AbsPosition;
99 ar_nodes[m_mouse_grab_node].Forces += m_mouse_grab_move_force * dir;
103 void Actor::CalcAircraftForces(
bool doUpdate)
110 for (
int i = 0; i < ar_num_aeroengines; i++)
111 if (ar_aeroengines[i])
112 ar_aeroengines[i]->updateForces(
PHYSICS_DT, doUpdate);
115 for (
int i = 0; i < ar_num_screwprops; i++)
116 if (ar_screwprops[i])
117 ar_screwprops[i]->updateForces(doUpdate);
120 for (
int i = 0; i < ar_num_wings; i++)
122 ar_wings[i].fa->updateForces();
125 void Actor::CalcFuseDrag()
127 if (m_fusealge_airfoil && m_fusealge_width > 0.0f)
129 Vector3 wind = -m_fusealge_front->Velocity;
130 float wspeed = wind.length();
131 Vector3 axis = m_fusealge_front->RelPosition - m_fusealge_back->RelPosition;
132 float s = axis.length() * m_fusealge_width;
134 float v = axis.getRotationTo(wind).w;
136 if (v < 1.0 && v > -1.0)
138 m_fusealge_airfoil->getparams(aoa, 1.0, 0.0, &cz, &cx, &cm);
141 float altitude = m_fusealge_front->AbsPosition.y;
142 float sea_level_pressure = 101325;
143 float airpressure = sea_level_pressure *
approx_pow(1.0 - 0.0065 * altitude / 288.1, 5.24947);
144 float airdensity = airpressure * 0.0000120896f;
147 ar_fusedrag = ((cx * s + m_fusealge_width * m_fusealge_width * 0.5) * 0.5 * airdensity * wspeed / ar_num_nodes) * wind;
151 void Actor::CalcBuoyance(
bool doUpdate)
155 for (
int i = 0; i < ar_num_buoycabs; i++)
157 int tmpv = ar_buoycabs[i] * 3;
158 m_buoyance->computeNodeForce(&ar_nodes[ar_cabs[tmpv]], &ar_nodes[ar_cabs[tmpv + 1]], &ar_nodes[ar_cabs[tmpv + 2]], doUpdate == 1, ar_buoycab_types[i]);
163 void Actor::CalcDifferentials()
165 if (ar_engine && m_num_proped_wheels > 0)
167 float torque = ar_engine->GetTorque() / m_num_proped_wheels;
168 if (m_has_axles_section)
172 for (
int i = 0; i < ar_num_wheels; i++)
174 if (ar_wheels[i].wh_propulsed && !ar_wheels[i].wh_is_detached)
175 ar_wheels[i].wh_torque += torque;
179 int num_axle_diffs = (m_transfer_case && m_transfer_case->tr_4wd_mode) ? m_num_axle_diffs + 1 : m_num_axle_diffs;
182 for (
int i = 0; i < num_axle_diffs; i++)
184 int a_1 = m_axle_diffs[i]->di_idx_1;
185 int a_2 = m_axle_diffs[i]->di_idx_2;
186 wheel_t* axle_1_wheels[2] = {&ar_wheels[m_wheel_diffs[a_1]->di_idx_1], &ar_wheels[m_wheel_diffs[a_1]->di_idx_2]};
187 wheel_t* axle_2_wheels[2] = {&ar_wheels[m_wheel_diffs[a_2]->di_idx_1], &ar_wheels[m_wheel_diffs[a_2]->di_idx_2]};
188 if (axle_1_wheels[0]->wh_is_detached && axle_1_wheels[1]->wh_is_detached)
193 if (axle_2_wheels[0]->wh_is_detached && axle_2_wheels[1]->wh_is_detached)
199 for (
int i = 0; i < m_num_wheel_diffs; i++)
201 wheel_t* axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]};
202 if (axle_wheels[0]->wh_is_detached) axle_wheels[0]->
wh_speed = axle_wheels[1]->
wh_speed;
203 if (axle_wheels[1]->wh_is_detached) axle_wheels[1]->
wh_speed = axle_wheels[0]->
wh_speed;
208 for (
int i = 0; i < num_axle_diffs; i++)
210 int a_1 = m_axle_diffs[i]->di_idx_1;
211 int a_2 = m_axle_diffs[i]->di_idx_2;
213 Ogre::Real axle_torques[2] = {0.0f, 0.0f};
217 (ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_speed + ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_speed) * 0.5f,
218 (ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_speed + ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_speed) * 0.5f
220 m_axle_diffs[i]->di_delta_rotation,
221 {axle_torques[0], axle_torques[1]},
222 ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_torque + ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_torque +
223 ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_torque + ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_torque,
227 m_axle_diffs[i]->CalcAxleTorque(diff_data);
231 ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_torque = diff_data.
out_torque[0] * 0.5f;
232 ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_torque = diff_data.
out_torque[0] * 0.5f;
233 ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_torque = diff_data.
out_torque[1] * 0.5f;
234 ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_torque = diff_data.
out_torque[1] * 0.5f;
239 for (
int i = 0; i < m_num_wheel_diffs; i++)
241 Ogre::Real axle_torques[2] = {0.0f, 0.0f};
242 wheel_t* axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]};
247 m_wheel_diffs[i]->di_delta_rotation,
248 {axle_torques[0], axle_torques[1]},
253 m_wheel_diffs[i]->CalcAxleTorque(diff_data);
257 ar_wheels[m_wheel_diffs[i]->di_idx_1].wh_torque = diff_data.
out_torque[0];
258 ar_wheels[m_wheel_diffs[i]->di_idx_2].wh_torque = diff_data.
out_torque[1];
262 void Actor::CalcWheels(
bool doUpdate,
int num_steps)
268 if (alb_timer >= alb_pulse_time)
271 alb_pulse_state = !alb_pulse_state;
273 if (tc_timer >= tc_pulse_time)
276 tc_pulse_state = !tc_pulse_state;
279 m_antilockbrake =
false;
280 m_tractioncontrol =
false;
282 ar_wheel_spin = 0.0f;
283 ar_wheel_speed = 0.0f;
285 for (
int i = 0; i < ar_num_wheels; i++)
289 ar_wheels[i].debug_rpm = 0.0f;
290 ar_wheels[i].debug_torque = 0.0f;
291 ar_wheels[i].debug_vel = Vector3::ZERO;
292 ar_wheels[i].debug_slip = Vector3::ZERO;
293 ar_wheels[i].debug_force = Vector3::ZERO;
294 ar_wheels[i].debug_scaled_cforce = Vector3::ZERO;
297 if (ar_wheels[i].wh_is_detached)
300 float relspeed = ar_nodes[0].Velocity.dotProduct(getDirection());
301 float curspeed = fabs(relspeed);
302 float wheel_slip = fabs(ar_wheels[i].wh_speed - relspeed) / std::max(1.0f, curspeed);
305 if (tc_mode && fabs(ar_wheels[i].wh_torque) > 0.0f && fabs(ar_wheels[i].wh_speed) > curspeed && wheel_slip > 0.25f)
309 ar_wheels[i].wh_tc_coef = curspeed / fabs(ar_wheels[i].wh_speed);
310 ar_wheels[i].wh_tc_coef = pow(ar_wheels[i].wh_tc_coef, tc_ratio);
312 float tc_coef = pow(ar_wheels[i].wh_tc_coef, std::min(std::abs(ar_wheels[i].wh_speed) / 5.0f, 1.0f));
313 ar_wheels[i].wh_torque *= tc_coef;
314 m_tractioncontrol =
true;
318 ar_wheels[i].wh_tc_coef = 1.0f;
321 if (ar_wheels[i].wh_braking != wheel_t::BrakeCombo::NONE)
324 float abrake = ar_brake_force * ar_brake;
328 if (ar_parking_brake && (ar_wheels[i].wh_braking != wheel_t::BrakeCombo::FOOT_ONLY))
330 hbrake = m_handbrake_force;
335 if ((ar_wheels[i].wh_speed < 20.0f)
336 && (((ar_wheels[i].wh_braking == wheel_t::BrakeCombo::FOOT_HAND_SKID_LEFT) && (ar_hydro_dir_state > 0.0f))
337 || ((ar_wheels[i].wh_braking == wheel_t::BrakeCombo::FOOT_HAND_SKID_RIGHT) && (ar_hydro_dir_state < 0.0f))))
339 dbrake = ar_brake_force * abs(ar_hydro_dir_state);
342 if (abrake != 0.0 || dbrake != 0.0 || hbrake != 0.0)
344 float adbrake = abrake + dbrake;
347 if (alb_mode && curspeed > alb_minspeed && curspeed > fabs(ar_wheels[i].wh_speed) && (adbrake > 0.0f) && wheel_slip > 0.25f)
351 ar_wheels[i].wh_alb_coef = fabs(ar_wheels[i].wh_speed) / curspeed;
352 ar_wheels[i].wh_alb_coef = pow(ar_wheels[i].wh_alb_coef, alb_ratio);
354 adbrake *= ar_wheels[i].wh_alb_coef;
355 m_antilockbrake =
true;
358 float force = -ar_wheels[i].wh_avg_speed * ar_wheels[i].wh_radius * ar_wheels[i].wh_mass /
PHYSICS_DT;
359 force -= ar_wheels[i].wh_last_retorque;
361 if (ar_wheels[i].wh_speed > 0)
362 ar_wheels[i].wh_torque += Math::Clamp(force, -(adbrake + hbrake), 0.0f);
364 ar_wheels[i].wh_torque += Math::Clamp(force, 0.0f, +(adbrake + hbrake));
368 ar_wheels[i].wh_alb_coef = 1.0f;
372 ar_wheels[i].debug_torque += ar_wheels[i].wh_torque / (float)num_steps;
375 Vector3 axis = (ar_wheels[i].wh_axis_node_1->RelPosition - ar_wheels[i].wh_axis_node_0->RelPosition).normalisedCopy();
376 float axis_precalc = ar_wheels[i].wh_torque / (Real)(ar_wheels[i].wh_num_nodes);
378 float expected_wheel_speed = ar_wheels[i].wh_speed;
379 ar_wheels[i].wh_speed = 0.0f;
381 Real contact_counter = 0.0f;
382 Vector3 slip = Vector3::ZERO;
383 Vector3 force = Vector3::ZERO;
384 for (
int j = 0; j < ar_wheels[i].wh_num_nodes; j++)
386 node_t* outer_node = ar_wheels[i].wh_nodes[j];
387 node_t* inner_node = (j % 2) ? ar_wheels[i].wh_axis_node_1 : ar_wheels[i].wh_axis_node_0;
390 float inverted_rlen = 1.0f / radius.length();
392 if (ar_wheels[i].wh_propulsed == 2)
397 Vector3 dir = axis.crossProduct(radius) * inverted_rlen;
398 ar_wheels[i].wh_nodes[j]->Forces += dir * axis_precalc * inverted_rlen;
399 ar_wheels[i].wh_speed += (outer_node->
Velocity - inner_node->
Velocity).dotProduct(dir);
401 if (ar_wheels[i].wh_nodes[j]->nd_has_ground_contact || ar_wheels[i].wh_nodes[j]->nd_has_mesh_contact)
403 contact_counter += 1.0f;
404 float force_ratio = ar_wheels[i].wh_nodes[j]->nd_last_collision_force.length();
405 slip += ar_wheels[i].wh_nodes[j]->nd_last_collision_slip * force_ratio;
406 force += ar_wheels[i].wh_nodes[j]->nd_last_collision_force;
409 if (contact_counter > 0.0f && !force.isZeroLength())
411 slip /= force.length();
412 slip /= contact_counter;
413 force /= contact_counter;
414 Vector3 normal = force.normalisedCopy();
415 Vector3 v = ar_wheels[i].wh_axis_node_0->Velocity.midPoint(ar_wheels[i].wh_axis_node_1->Velocity);
416 Vector3 vel = v - v.dotProduct(normal) * normal;
417 ar_wheels[i].debug_vel += vel / (float)num_steps;
418 ar_wheels[i].debug_slip += slip / (float)num_steps;
419 ar_wheels[i].debug_force += force / (float)num_steps;
422 ar_wheels[i].wh_speed /= (Real)ar_wheels[i].wh_num_nodes;
423 ar_wheels[i].wh_net_rp += (ar_wheels[i].wh_speed / ar_wheels[i].wh_radius) *
PHYSICS_DT;
425 ar_wheels[i].wh_avg_speed = ar_wheels[i].wh_avg_speed * 0.99 + ar_wheels[i].wh_speed * 0.1;
426 ar_wheels[i].debug_rpm +=
RAD_PER_SEC_TO_RPM * ar_wheels[i].wh_speed / ar_wheels[i].wh_radius / (float)num_steps;
427 if (ar_wheels[i].wh_propulsed == 1)
429 float speedacc = ar_wheels[i].wh_speed / (float)m_num_proped_wheels;
430 ar_wheel_speed += speedacc;
431 ar_wheel_spin += speedacc / ar_wheels[i].wh_radius;
434 expected_wheel_speed += ((ar_wheels[i].wh_last_torque / ar_wheels[i].wh_radius) / ar_wheels[i].wh_mass) *
PHYSICS_DT;
435 ar_wheels[i].wh_last_retorque = ar_wheels[i].wh_mass * (ar_wheels[i].wh_speed - expected_wheel_speed) /
PHYSICS_DT;
438 Vector3 rradius = ar_wheels[i].wh_arm_node->RelPosition - ar_wheels[i].wh_near_attach_node->RelPosition;
439 Vector3 radius = Plane(axis, ar_wheels[i].wh_near_attach_node->RelPosition).projectVector(rradius);
440 float offset = (rradius - radius).length();
441 Real rlen = radius.normalise();
443 if (rlen > 0.01 && offset * 2.0f < rlen && fabs(ar_wheels[i].wh_torque) > 0.01f)
445 Vector3 cforce = axis.crossProduct(radius);
447 cforce *= (0.5f * ar_wheels[i].wh_torque / rlen) * (1.0f - ((offset * 2.0f) / rlen));
448 ar_wheels[i].wh_arm_node->Forces -= cforce;
449 ar_wheels[i].wh_near_attach_node->Forces += cforce;
450 ar_wheels[i].debug_scaled_cforce += cforce / m_total_mass / (float)num_steps;
453 ar_wheels[i].wh_last_torque = ar_wheels[i].wh_torque;
454 ar_wheels[i].wh_torque = 0.0f;
457 ar_avg_wheel_speed = ar_avg_wheel_speed * 0.995 + ar_wheel_speed * 0.005;
466 if (!m_antilockbrake)
475 if (!m_tractioncontrol)
486 float distance_driven = fabs(ar_wheel_speed *
PHYSICS_DT);
487 m_odometer_total += distance_driven;
488 m_odometer_user += distance_driven;
491 void Actor::CalcShocks(
bool doUpdate,
int num_steps)
494 if (this->ar_has_active_shocks && m_stabilizer_shock_request)
496 if ((m_stabilizer_shock_request == 1 && m_stabilizer_shock_ratio < 0.1) || (m_stabilizer_shock_request == -1 && m_stabilizer_shock_ratio > -0.1))
497 m_stabilizer_shock_ratio = m_stabilizer_shock_ratio + (float)m_stabilizer_shock_request *
PHYSICS_DT *
STAB_RATE;
498 for (
int i = 0; i < ar_num_shocks; i++)
502 ar_beams[ar_shocks[i].beamid].L = ar_beams[ar_shocks[i].beamid].refL * (1.0 + m_stabilizer_shock_ratio);
504 ar_beams[ar_shocks[i].beamid].L = ar_beams[ar_shocks[i].beamid].refL * (1.0 - m_stabilizer_shock_ratio);
508 if (this->ar_has_active_shocks && doUpdate)
510 m_stabilizer_shock_sleep -=
PHYSICS_DT * num_steps;
512 float roll = asin(GetCameraRoll().dotProduct(Vector3::UNIT_Y));
514 if (fabs(roll) > 0.2)
516 m_stabilizer_shock_sleep = -1.0;
518 if (fabs(roll) > 0.01 && m_stabilizer_shock_sleep < 0.0)
520 if (roll > 0.0 && m_stabilizer_shock_request != -1)
522 m_stabilizer_shock_request = 1;
524 else if (roll < 0.0 && m_stabilizer_shock_request != 1)
526 m_stabilizer_shock_request = -1;
530 m_stabilizer_shock_request = 0;
531 m_stabilizer_shock_sleep = 3.0;
536 m_stabilizer_shock_request = 0;
539 if (m_stabilizer_shock_request && fabs(m_stabilizer_shock_ratio) < 0.1)
546 void Actor::CalcHydros()
549 if (ar_hydro_dir_state != 0 || ar_hydro_dir_command != 0)
551 if (!ar_hydro_speed_coupling)
556 float diff = ar_hydro_dir_command - ar_hydro_dir_state;
557 float rate = std::exp(-std::min(std::abs(diff), 1.0f) / sensitivity) * diff;
558 ar_hydro_dir_state += (10.0f / smoothing) *
PHYSICS_DT * rate;
562 if (ar_hydro_dir_command != 0)
566 float rate = std::max(1.2f, 30.0f / (10.0f));
567 if (ar_hydro_dir_state > ar_hydro_dir_command)
575 float rate = std::max(1.2f, 30.0f / (10.0f + std::abs(ar_wheel_speed / 2.0f)));
576 if (ar_hydro_dir_state > ar_hydro_dir_command)
583 if (ar_hydro_dir_state > dirdelta)
584 ar_hydro_dir_state -= dirdelta;
585 else if (ar_hydro_dir_state < -dirdelta)
586 ar_hydro_dir_state += dirdelta;
588 ar_hydro_dir_state = 0;
592 if (ar_hydro_aileron_state != 0 || ar_hydro_aileron_command != 0)
594 if (ar_hydro_aileron_command != 0)
596 if (ar_hydro_aileron_state > ar_hydro_aileron_command)
602 if (ar_hydro_aileron_state > delta)
603 ar_hydro_aileron_state -= delta;
604 else if (ar_hydro_aileron_state < -delta)
605 ar_hydro_aileron_state += delta;
607 ar_hydro_aileron_state = 0;
610 if (ar_hydro_rudder_state != 0 || ar_hydro_rudder_command != 0)
612 if (ar_hydro_rudder_command != 0)
614 if (ar_hydro_rudder_state > ar_hydro_rudder_command)
621 if (ar_hydro_rudder_state > delta)
622 ar_hydro_rudder_state -= delta;
623 else if (ar_hydro_rudder_state < -delta)
624 ar_hydro_rudder_state += delta;
626 ar_hydro_rudder_state = 0;
629 if (ar_hydro_elevator_state != 0 || ar_hydro_elevator_command != 0)
631 if (ar_hydro_elevator_command != 0)
633 if (ar_hydro_elevator_state > ar_hydro_elevator_command)
639 if (ar_hydro_elevator_state > delta)
640 ar_hydro_elevator_state -= delta;
641 else if (ar_hydro_elevator_state < -delta)
642 ar_hydro_elevator_state += delta;
644 ar_hydro_elevator_state = 0;
647 const int num_hydros =
static_cast<int>(ar_hydros.size());
648 for (
int i = 0; i < num_hydros; ++i)
658 if (ar_wheel_speed < 12.0f)
659 cstate += ar_hydro_dir_state * (12.0f - ar_wheel_speed) / 12.0f;
664 cstate += ar_hydro_dir_state;
669 cstate += ar_hydro_aileron_state;
674 cstate += ar_hydro_rudder_state;
679 cstate += ar_hydro_elevator_state;
684 cstate -= ar_hydro_aileron_state;
689 cstate -= ar_hydro_rudder_state;
694 cstate -= ar_hydro_elevator_state;
708 this->CalcAnimators(hydrobeam, cstate, div);
714 cstate /= (float)div;
719 ar_hydro_dir_wheel_display = cstate;
721 float factor = 1.0 - cstate * hydrobeam.
hb_speed;
726 if (factor < 1.0f - ar_beams[beam_idx].shortbound)
727 factor = 1.0f - ar_beams[beam_idx].shortbound;
728 if (factor > 1.0f + ar_beams[beam_idx].longbound)
729 factor = 1.0f + ar_beams[beam_idx].longbound;
737 void Actor::CalcCommands(
bool doUpdate)
739 if (m_has_command_beams)
742 bool requested =
false;
747 ar_engine_hydraulics_ready = ar_engine->GetEngineRpm() > ar_engine->getIdleRPM() * 0.95f;
749 ar_engine_hydraulics_ready =
true;
752 float crankfactor = 1.0f;
754 crankfactor = ar_engine->GetCrankFactor();
762 for (
int j = 0; j < (int)ar_command_key[i].beams.size(); j++)
764 ar_command_key[i].beams[j].cmb_state->auto_move_lock =
false;
770 float oldValue = ar_command_key[i].commandValue;
772 ar_command_key[i].commandValue = std::max(ar_command_key[i].playerInputValue, ar_command_key[i].triggerInputValue);
774 ar_command_key[i].triggerInputValue = 0.0f;
776 if (ar_command_key[i].commandValue > 0.01f && oldValue < 0.01f)
779 ar_command_key[i].commandValueState = 1;
781 else if (ar_command_key[i].commandValue < 0.01f && oldValue > 0.01f)
784 ar_command_key[i].commandValueState = -1;
787 for (
int j = 0; j < (int)ar_command_key[i].beams.size(); j++)
789 if (ar_command_key[i].commandValue >= 0.5)
791 ar_command_key[i].beams[j].cmb_state->auto_move_lock =
true;
792 if (ar_command_key[i].beams[j].cmb_is_autocentering)
794 ar_command_key[i].beams[j].cmb_state->auto_moving_mode = 0;
803 bool requestpower =
false;
804 for (
int j = 0; j < (int)ar_command_key[i].beams.size(); j++)
810 if (bbeam > ar_num_beams)
815 crankfactor = std::min(crankfactor, 1.0f);
817 float v = ar_command_key[i].commandValue;
818 int& vst = ar_command_key[i].commandValueState;
824 if (ar_beams[bbeam].refL == 0 || ar_beams[bbeam].L == 0)
827 float current = (ar_beams[bbeam].L / ar_beams[bbeam].refL);
832 cmd_beam.
cmb_state->auto_moving_mode = 0;
836 int mode = cmd_beam.
cmb_state->auto_moving_mode;
840 cmd_beam.
cmb_state->auto_moving_mode = -1;
842 cmd_beam.
cmb_state->auto_moving_mode = 1;
845 if (mode != 0 && mode != cmd_beam.
cmb_state->auto_moving_mode)
848 cmd_beam.
cmb_state->auto_moving_mode = 0;
853 if (ar_beams[bbeam].refL != 0 && ar_beams[bbeam].L != 0)
855 float clen = ar_beams[bbeam].L / ar_beams[bbeam].refL;
858 float dl = ar_beams[bbeam].L;
865 cmd_beam.
cmb_state->pressed_center_mode =
true;
866 cmd_beam.
cmb_state->auto_moving_mode = 0;
870 cmd_beam.
cmb_state->pressed_center_mode =
false;
875 bool key = (v > 0.5);
876 if (bbeam_dir * cmd_beam.
cmb_state->auto_moving_mode <= 0 && key)
878 cmd_beam.
cmb_state->auto_moving_mode = bbeam_dir * 1;
880 else if (cmd_beam.
cmb_state->auto_moving_mode == bbeam_dir * 1 && !key)
882 cmd_beam.
cmb_state->auto_moving_mode = bbeam_dir * 2;
884 else if (cmd_beam.
cmb_state->auto_moving_mode == bbeam_dir * 2 && key)
886 cmd_beam.
cmb_state->auto_moving_mode = bbeam_dir * 3;
888 else if (cmd_beam.
cmb_state->auto_moving_mode == bbeam_dir * 3 && !key)
890 cmd_beam.
cmb_state->auto_moving_mode = 0;
894 v = ar_command_key[i].command_inertia.CalcCmdKeyDelay(v,
PHYSICS_DT);
896 if (bbeam_dir * cmd_beam.
cmb_state->auto_moving_mode > 0)
899 if (cmd_beam.
cmb_needs_engine && ((ar_engine && !ar_engine->isRunning()) || !ar_engine_hydraulics_ready))
939 dl = fabs(dl - ar_beams[bbeam].L);
949 cmd_beam.
cmb_state->auto_moving_mode = 0;
954 for (
int j = 0; j < (int)ar_command_key[i].rotators.size(); j++)
957 int rota = std::abs(ar_command_key[i].rotators[j]) - 1;
959 if (ar_rotators[rota].needs_engine && ((ar_engine && !ar_engine->isRunning()) || !ar_engine_hydraulics_ready))
962 v = ar_command_key[i].rotator_inertia.CalcCmdKeyDelay(ar_command_key[i].commandValue,
PHYSICS_DT);
964 if (v > 0.0f && ar_rotators[rota].engine_coupling > 0.0f)
969 if (ar_rotators[rota].engine_coupling > 0.0f)
972 if (ar_command_key[i].rotators[j] > 0)
973 ar_rotators[rota].angle += ar_rotators[rota].rate * v * cf *
PHYSICS_DT;
975 ar_rotators[rota].angle -= ar_rotators[rota].rate * v * cf *
PHYSICS_DT;
977 if (doUpdate || v != 0.0f)
979 ar_rotators[rota].debug_rate = ar_rotators[rota].rate * v * cf;
988 ar_engine->SetHydroPumpWork(work);
989 ar_engine->SetEnginePriming(requested);
998 float pump_rpm = 660.0f * (1.0f - (work / (float)active) / 100.0f);
1008 for (
int i = 0; i < ar_num_rotators; i++)
1011 Vector3 ax1 = ar_nodes[ar_rotators[i].axis1].RelPosition;
1012 Vector3 ax2 = ar_nodes[ar_rotators[i].axis2].RelPosition;
1013 Vector3 axis = ax1 - ax2;
1016 Plane pl = Plane(axis, 0);
1018 ar_rotators[i].debug_aerror = 0;
1019 for (
int k = 0; k < 2; k++)
1022 Vector3 ref1 = pl.projectVector(ax1 - ar_nodes[ar_rotators[i].nodes1[k]].RelPosition);
1023 Vector3 ref2 = pl.projectVector(ax2 - ar_nodes[ar_rotators[i].nodes2[k]].RelPosition);
1024 float ref1len = ref1.normalise();
1025 float ref2len = ref2.normalise();
1027 Vector3 th1 = Quaternion(Radian(ar_rotators[i].angle + Math::HALF_PI), axis) * ref1;
1029 float aerror = asin(th1.dotProduct(ref2));
1030 ar_rotators[i].debug_aerror += 0.5f * aerror;
1032 float rigidity = ar_rotators[i].force;
1033 Vector3 dir1 = ref1.crossProduct(axis);
1034 Vector3 dir2 = ref2.crossProduct(axis);
1037 if (ref1len <= ar_rotators[i].tolerance)
1039 if (ref2len <= ar_rotators[i].tolerance)
1042 ar_nodes[ar_rotators[i].nodes1[k ]].Forces += (aerror * ref1len * rigidity) * dir1;
1043 ar_nodes[ar_rotators[i].nodes2[k ]].Forces -= (aerror * ref2len * rigidity) * dir2;
1045 ar_nodes[ar_rotators[i].nodes1[k + 2]].Forces -= (aerror * ref1len * rigidity) * dir1;
1046 ar_nodes[ar_rotators[i].nodes2[k + 2]].Forces += (aerror * ref2len * rigidity) * dir2;
1052 void Actor::CalcTies()
1055 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
1062 if (it->ti_beam->refL == 0 || it->ti_beam->L == 0)
1065 float clen = it->ti_beam->L / it->ti_beam->refL;
1066 if (clen > it->ti_min_length)
1068 it->ti_beam->L *= (1.0 - it->ti_contract_speed *
PHYSICS_DT / it->ti_beam->L);
1073 it->ti_tying =
false;
1077 if (fabs(it->ti_beam->stress) > it->ti_max_stress)
1079 it->ti_tying =
false;
1083 void Actor::CalcTruckEngine(
bool doUpdate)
1087 ar_engine->UpdateEngineSim(
PHYSICS_DT, doUpdate);
1091 void Actor::CalcReplay()
1093 if (m_replay_handler && m_replay_handler->isValid())
1095 m_replay_handler->onPhysicsStep();
1099 bool Actor::CalcForcesEulerPrepare(
bool doUpdate)
1101 if (m_ongoing_reset)
1103 if (ar_physics_paused)
1105 if (ar_state != ActorState::LOCAL_SIMULATED)
1112 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
1127 msg <<
" (index: " << node->
pos <<
")";
1133 msg <<
"It was between nodes ";
1140 void Actor::CalcBeams(
bool trigger_hooks)
1142 for (
int i = 0; i < ar_num_beams; i++)
1144 if (!ar_beams[i].bm_disabled && !ar_beams[i].bm_inter_actor)
1147 Vector3 dis = ar_beams[i].p1->RelPosition - ar_beams[i].p2->RelPosition;
1149 Real dislen = dis.squaredLength();
1152 dislen *= inverted_dislen;
1155 Real difftoBeamL = dislen - ar_beams[i].L;
1157 Real k = ar_beams[i].k;
1158 Real d = ar_beams[i].d;
1161 float v = (ar_beams[i].p1->Velocity - ar_beams[i].p2->Velocity).dotProduct(dis) * inverted_dislen;
1163 if (ar_beams[i].bounded ==
SHOCK1)
1165 float interp_ratio = 0.0f;
1168 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
1169 interp_ratio = difftoBeamL - ar_beams[i].longbound * ar_beams[i].L;
1170 else if (difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
1171 interp_ratio = -difftoBeamL - ar_beams[i].shortbound * ar_beams[i].L;
1173 if (interp_ratio != 0.0f)
1182 tspring = ar_beams[i].shock->sbd_spring;
1183 tdamp = ar_beams[i].shock->sbd_damp;
1186 k += (tspring - k) * interp_ratio;
1187 d += (tdamp - d) * interp_ratio;
1190 else if (ar_beams[i].bounded ==
TRIGGER)
1192 this->CalcTriggers(i, difftoBeamL, trigger_hooks);
1194 else if (ar_beams[i].bounded ==
SHOCK2)
1196 this->CalcShocks2(i, difftoBeamL, k, d, v);
1198 else if (ar_beams[i].bounded ==
SHOCK3)
1200 this->CalcShocks3(i, difftoBeamL, k, d, v);
1204 if (difftoBeamL > 0.0f)
1209 if (ar_beams[i].longbound > 0.0f)
1212 break_limit = ar_beams[i].longbound;
1216 if (difftoBeamL > ar_beams[i].L * break_limit)
1218 ar_beams[i].bm_broken =
true;
1219 ar_beams[i].bm_disabled =
true;
1220 if (m_beam_break_debug_enabled)
1223 msg <<
"[RoR|Diag] XXX Support-Beam " << i <<
" limit extended and broke. "
1224 <<
"Length: " << difftoBeamL <<
" / max. Length: " << (ar_beams[i].L*break_limit) <<
". ";
1231 else if (ar_beams[i].bounded ==
ROPE)
1233 if (difftoBeamL < 0.0f)
1240 if (trigger_hooks && ar_beams[i].bounded && ar_beams[i].bm_type ==
BEAM_HYDRO)
1242 ar_beams[i].debug_k = k * std::abs(difftoBeamL);
1243 ar_beams[i].debug_d = d * std::abs(v);
1244 ar_beams[i].debug_v = std::abs(v);
1247 float slen = -k * difftoBeamL - d * v;
1248 ar_beams[i].stress = slen;
1251 float len = std::abs(slen);
1252 if (len > ar_beams[i].minmaxposnegstress)
1254 if (ar_beams[i].bm_type ==
BEAM_NORMAL && ar_beams[i].bounded !=
SHOCK1 && k != 0.0f)
1257 if (slen > ar_beams[i].maxposstress && difftoBeamL < 0.0f)
1259 Real yield_length = ar_beams[i].maxposstress / k;
1260 Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef);
1261 Real Lold = ar_beams[i].L;
1262 ar_beams[i].L += deform;
1264 slen = slen - (slen - ar_beams[i].maxposstress) * 0.5f;
1266 if (ar_beams[i].L > 0.0f && Lold > ar_beams[i].L)
1268 ar_beams[i].maxposstress *= Lold / ar_beams[i].L;
1269 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].maxposstress, -ar_beams[i].maxnegstress);
1270 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].minmaxposnegstress, ar_beams[i].strength);
1275 if (m_beam_deform_debug_enabled)
1278 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1279 << len <<
" / " << ar_beams[i].strength <<
". ";
1284 else if (slen < ar_beams[i].maxnegstress && difftoBeamL > 0.0f)
1286 Real yield_length = ar_beams[i].maxnegstress / k;
1287 Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef);
1288 Real Lold = ar_beams[i].L;
1289 ar_beams[i].L += deform;
1290 slen = slen - (slen - ar_beams[i].maxnegstress) * 0.5f;
1292 if (Lold > 0.0f && ar_beams[i].L > Lold)
1294 ar_beams[i].maxnegstress *= ar_beams[i].L / Lold;
1295 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].maxposstress, -ar_beams[i].maxnegstress);
1296 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].minmaxposnegstress, ar_beams[i].strength);
1298 ar_beams[i].strength -= deform * k;
1299 if (m_beam_deform_debug_enabled)
1302 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1303 << len <<
" / " << ar_beams[i].strength <<
". ";
1311 if (len > ar_beams[i].strength)
1321 if (!((ar_beams[i].p1->nd_cab_node && GetNumActiveConnectedBeams(ar_beams[i].p1->pos) < 3) || (ar_beams[i].p2->nd_cab_node && GetNumActiveConnectedBeams(ar_beams[i].p2->pos) < 3)))
1324 ar_beams[i].bm_broken =
true;
1325 ar_beams[i].bm_disabled =
true;
1327 if (m_beam_break_debug_enabled)
1330 msg <<
"[RoR|Diag] XXX Beam " << i <<
" just broke with force " << len <<
" / " << ar_beams[i].strength <<
". ";
1337 if (ar_beams[i].detacher_group > 0)
1340 for (
int j = 0; j < ar_num_beams; j++)
1344 if (abs(ar_beams[j].detacher_group) == ar_beams[i].detacher_group)
1346 ar_beams[j].bm_broken =
true;
1347 ar_beams[j].bm_disabled =
true;
1348 if (m_beam_break_debug_enabled)
1351 "Deleting Detacher BeamID: " +
TOSTRING(j) +
", Detacher Group: " +
TOSTRING(ar_beams[i].detacher_group)+
", actor ID: " +
TOSTRING(ar_instance_id));
1358 if (wheeldetacher.wd_detacher_group == ar_beams[i].detacher_group)
1360 ar_wheels[wheeldetacher.wd_wheel_id].wh_is_detached =
true;
1361 if (m_beam_break_debug_enabled)
1364 "Detaching wheel ID: " +
TOSTRING(wheeldetacher.wd_wheel_id) +
", Detacher Group: " +
TOSTRING(ar_beams[i].detacher_group)+
", actor ID: " +
TOSTRING(ar_instance_id));
1372 ar_beams[i].strength = 2.0f * ar_beams[i].minmaxposnegstress;
1376 for (
int mk = 0; mk < ar_num_buoycabs; mk++)
1378 int tmpv = ar_buoycabs[mk] * 3;
1379 if (ar_buoycab_types[mk] == Buoyance::BUOY_DRAGONLY)
1381 if ((ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv]] || ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv + 1]] || ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv + 2]]) &&
1382 (ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv]] || ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv + 1]] || ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv + 2]]))
1384 m_buoyance->sink =
true;
1392 f *= (slen * inverted_dislen);
1393 ar_beams[i].p1->Forces += f;
1394 ar_beams[i].p2->Forces -= f;
1399 void Actor::CalcBeamsInterActor()
1401 for (
int i = 0; i < static_cast<int>(ar_inter_beams.size()); i++)
1403 if (!ar_inter_beams[i]->bm_disabled && ar_inter_beams[i]->bm_inter_actor)
1406 Vector3 dis = ar_inter_beams[i]->p1->AbsPosition - ar_inter_beams[i]->p2->AbsPosition;
1408 Real dislen = dis.squaredLength();
1411 dislen *= inverted_dislen;
1414 Real difftoBeamL = dislen - ar_inter_beams[i]->L;
1416 Real k = ar_inter_beams[i]->k;
1417 Real d = ar_inter_beams[i]->d;
1419 if (ar_inter_beams[i]->bounded ==
ROPE && difftoBeamL < 0.0f)
1426 Vector3 v = ar_inter_beams[i]->p1->Velocity - ar_inter_beams[i]->p2->Velocity;
1428 float slen = -k * (difftoBeamL) - d * v.dotProduct(dis) * inverted_dislen;
1429 ar_inter_beams[i]->stress = slen;
1432 float len = std::abs(slen);
1433 if (len > ar_inter_beams[i]->minmaxposnegstress)
1435 if (ar_inter_beams[i]->bm_type ==
BEAM_NORMAL && ar_inter_beams[i]->bounded !=
SHOCK1 && k != 0.0f)
1438 if (slen > ar_inter_beams[i]->maxposstress && difftoBeamL < 0.0f)
1440 Real yield_length = ar_inter_beams[i]->maxposstress / k;
1441 Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef);
1442 Real Lold = ar_inter_beams[i]->L;
1443 ar_inter_beams[i]->L += deform;
1444 ar_inter_beams[i]->L = std::max(
MIN_BEAM_LENGTH, ar_inter_beams[i]->L);
1445 slen = slen - (slen - ar_inter_beams[i]->maxposstress) * 0.5f;
1447 if (ar_inter_beams[i]->L > 0.0f && Lold > ar_inter_beams[i]->L)
1449 ar_inter_beams[i]->maxposstress *= Lold / ar_inter_beams[i]->L;
1450 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress);
1451 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength);
1456 if (m_beam_deform_debug_enabled)
1459 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1460 << len <<
" / " << ar_inter_beams[i]->strength <<
". ";
1465 else if (slen < ar_inter_beams[i]->maxnegstress && difftoBeamL > 0.0f)
1467 Real yield_length = ar_inter_beams[i]->maxnegstress / k;
1468 Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef);
1469 Real Lold = ar_inter_beams[i]->L;
1470 ar_inter_beams[i]->L += deform;
1471 slen = slen - (slen - ar_inter_beams[i]->maxnegstress) * 0.5f;
1473 if (Lold > 0.0f && ar_inter_beams[i]->L > Lold)
1475 ar_inter_beams[i]->maxnegstress *= ar_inter_beams[i]->L / Lold;
1476 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress);
1477 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength);
1479 ar_inter_beams[i]->strength -= deform * k;
1480 if (m_beam_deform_debug_enabled)
1483 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1484 << len <<
" / " << ar_inter_beams[i]->strength <<
". ";
1492 if (len > ar_inter_beams[i]->strength)
1502 if (!((ar_inter_beams[i]->p1->nd_cab_node && GetNumActiveConnectedBeams(ar_inter_beams[i]->p1->pos) < 3) || (ar_inter_beams[i]->p2->nd_cab_node && GetNumActiveConnectedBeams(ar_inter_beams[i]->p2->pos) < 3)))
1505 ar_inter_beams[i]->bm_broken =
true;
1506 ar_inter_beams[i]->bm_disabled =
true;
1508 if (m_beam_break_debug_enabled)
1511 msg <<
"Beam " << i <<
" just broke with force " << len <<
" / " << ar_inter_beams[i]->strength <<
". ";
1518 ar_inter_beams[i]->strength = 2.0f * ar_inter_beams[i]->minmaxposnegstress;
1525 f *= (slen * inverted_dislen);
1526 ar_inter_beams[i]->p1->Forces += f;
1527 ar_inter_beams[i]->p2->Forces -= f;
1532 void Actor::CalcNodes()
1536 m_water_contact =
false;
1538 for (
NodeNum_t i = 0; i < ar_num_nodes; i++)
1541 if (!ar_nodes[i].nd_no_ground_contact)
1543 Vector3 oripos = ar_nodes[i].AbsPosition;
1546 ar_nodes[i].nd_has_ground_contact = contacted;
1547 if (ar_nodes[i].nd_has_ground_contact || ar_nodes[i].nd_has_mesh_contact)
1549 ar_last_fuzzy_ground_model = ar_nodes[i].nd_last_collision_gm;
1553 ar_nodes[i].RelPosition += ar_nodes[i].AbsPosition - oripos;
1557 if (i == ar_main_camera_node_pos)
1560 m_camera_gforces_accu += ar_nodes[i].Forces / ar_nodes[i].mass;
1564 if (!ar_nodes[i].nd_immovable)
1566 ar_nodes[i].Velocity += ar_nodes[i].Forces / ar_nodes[i].mass *
PHYSICS_DT;
1567 ar_nodes[i].RelPosition += ar_nodes[i].Velocity *
PHYSICS_DT;
1568 ar_nodes[i].AbsPosition = ar_origin;
1569 ar_nodes[i].AbsPosition += ar_nodes[i].RelPosition;
1575 ar_nodes[i].Forces = Vector3(0, ar_nodes[i].mass * gravity, 0);
1577 Real approx_speed =
approx_sqrt(ar_nodes[i].Velocity.squaredLength());
1580 if (approx_speed > 6860 && !m_ongoing_reset)
1584 rq->
amr_type = ActorModifyRequest::Type::RESET_ON_SPOT;
1586 m_ongoing_reset =
true;
1589 if (m_fusealge_airfoil)
1592 ar_nodes[i].Forces += ar_fusedrag;
1594 else if (!ar_disable_aerodyn_turbulent_drag)
1598 Vector3 drag = -defdragxspeed * ar_nodes[i].Velocity;
1600 Real maxtur = defdragxspeed * approx_speed * 0.005f;
1602 ar_nodes[i].Forces += drag;
1607 const bool is_under_water = water->IsUnderWater(ar_nodes[i].AbsPosition);
1610 m_water_contact =
true;
1611 if (ar_num_buoycabs == 0)
1614 ar_nodes[i].Forces -= (
DEFAULT_WATERDRAG * approx_speed) * ar_nodes[i].Velocity;
1616 ar_nodes[i].Forces += ar_nodes[i].buoyancy * Vector3::UNIT_Y;
1619 if (i == ar_cinecam_node[0] && ar_engine)
1621 ar_engine->StopEngine();
1624 ar_nodes[i].nd_under_water = is_under_water;
1638 void Actor::CalcEventBoxes()
1647 m_potential_eventboxes.clear();
1653 bool has_collision =
false;
1654 bool do_callback_enter =
true;
1655 bool do_callback_exit =
false;
1656 auto itor = m_active_eventboxes.begin();
1657 while (itor != m_active_eventboxes.end())
1659 if (itor->first == cbox)
1666 itor = m_active_eventboxes.erase(itor);
1668 do_callback_enter =
false;
1669 do_callback_exit =
true;
1682 for (
NodeNum_t i = 0; i < ar_num_nodes; i++)
1687 do_callback_exit =
false;
1689 m_active_eventboxes.push_back(std::make_pair(cbox, i));
1691 if (do_callback_enter)
1708 if (do_callback_exit)
1717 void Actor::CalcHooks()
1720 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
1723 it->hk_timer = std::max(0.0f, it->hk_timer -
PHYSICS_DT);
1725 if (it->hk_lock_node && it->hk_locked ==
PRELOCK)
1727 if (it->hk_beam->L < it->hk_min_length)
1735 if (it->hk_beam->L > it->hk_lockspeed && fabs(it->hk_beam->stress) < it->hk_maxforce)
1737 it->hk_beam->L = (it->hk_beam->L - it->hk_lockspeed);
1741 if (fabs(it->hk_beam->stress) < it->hk_maxforce)
1743 it->hk_beam->L = 0.001f;
1749 if (it->hk_nodisable)
1759 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
1769 void Actor::CalcRopes()
1771 for (
auto r : ar_ropes)
1773 if (r.rp_locked ==
LOCKED && r.rp_locked_ropable)
1775 auto locked_node = r.rp_locked_ropable->node;
1776 r.rp_beam->p2->AbsPosition = locked_node->AbsPosition;
1777 r.rp_beam->p2->RelPosition = locked_node->AbsPosition - ar_origin;
1778 r.rp_beam->p2->Velocity = locked_node->Velocity;
1779 locked_node->Forces += r.rp_beam->p2->Forces;
1780 r.rp_beam->p2->Forces = Vector3::ZERO;