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();
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 != WheelPropulsion::NONE && !ar_wheels[i].wh_is_detached)
176 ar_wheels[i].wh_torque += torque;
181 int num_axle_diffs = (m_transfer_case && m_transfer_case->tr_4wd_mode) ? m_num_axle_diffs + 1 : m_num_axle_diffs;
184 for (
int i = 0; i < num_axle_diffs; i++)
186 int a_1 = m_axle_diffs[i]->di_idx_1;
187 int a_2 = m_axle_diffs[i]->di_idx_2;
188 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]};
189 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]};
190 if (axle_1_wheels[0]->wh_is_detached && axle_1_wheels[1]->wh_is_detached)
195 if (axle_2_wheels[0]->wh_is_detached && axle_2_wheels[1]->wh_is_detached)
201 for (
int i = 0; i < m_num_wheel_diffs; i++)
203 wheel_t* axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]};
204 if (axle_wheels[0]->wh_is_detached) axle_wheels[0]->
wh_speed = axle_wheels[1]->
wh_speed;
205 if (axle_wheels[1]->wh_is_detached) axle_wheels[1]->
wh_speed = axle_wheels[0]->
wh_speed;
210 for (
int i = 0; i < num_axle_diffs; i++)
212 int a_1 = m_axle_diffs[i]->di_idx_1;
213 int a_2 = m_axle_diffs[i]->di_idx_2;
215 Ogre::Real axle_torques[2] = {0.0f, 0.0f};
219 (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,
220 (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
222 m_axle_diffs[i]->di_delta_rotation,
223 {axle_torques[0], axle_torques[1]},
224 ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_torque + ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_torque +
225 ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_torque + ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_torque,
229 m_axle_diffs[i]->CalcAxleTorque(diff_data);
233 ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_torque = diff_data.
out_torque[0] * 0.5f;
234 ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_torque = diff_data.
out_torque[0] * 0.5f;
235 ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_torque = diff_data.
out_torque[1] * 0.5f;
236 ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_torque = diff_data.
out_torque[1] * 0.5f;
241 for (
int i = 0; i < m_num_wheel_diffs; i++)
243 Ogre::Real axle_torques[2] = {0.0f, 0.0f};
244 wheel_t* axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]};
249 m_wheel_diffs[i]->di_delta_rotation,
250 {axle_torques[0], axle_torques[1]},
255 m_wheel_diffs[i]->CalcAxleTorque(diff_data);
259 ar_wheels[m_wheel_diffs[i]->di_idx_1].wh_torque = diff_data.
out_torque[0];
260 ar_wheels[m_wheel_diffs[i]->di_idx_2].wh_torque = diff_data.
out_torque[1];
264 void Actor::CalcWheels(
bool doUpdate,
int num_steps)
270 if (alb_timer >= alb_pulse_time)
273 alb_pulse_state = !alb_pulse_state;
275 if (tc_timer >= tc_pulse_time)
278 tc_pulse_state = !tc_pulse_state;
281 m_antilockbrake =
false;
282 m_tractioncontrol =
false;
284 ar_wheel_spin = 0.0f;
285 ar_wheel_speed = 0.0f;
287 for (
int i = 0; i < ar_num_wheels; i++)
291 ar_wheels[i].debug_rpm = 0.0f;
292 ar_wheels[i].debug_torque = 0.0f;
293 ar_wheels[i].debug_vel = Vector3::ZERO;
294 ar_wheels[i].debug_slip = Vector3::ZERO;
295 ar_wheels[i].debug_force = Vector3::ZERO;
296 ar_wheels[i].debug_scaled_cforce = Vector3::ZERO;
299 if (ar_wheels[i].wh_is_detached)
302 float relspeed = ar_nodes[0].Velocity.dotProduct(getDirection());
303 float curspeed = fabs(relspeed);
304 float wheel_slip = fabs(ar_wheels[i].wh_speed - relspeed) / std::max(1.0f, curspeed);
307 if (tc_mode && fabs(ar_wheels[i].wh_torque) > 0.0f && fabs(ar_wheels[i].wh_speed) > curspeed && wheel_slip > tc_wheelslip_constant)
311 ar_wheels[i].wh_tc_coef = curspeed / fabs(ar_wheels[i].wh_speed);
312 ar_wheels[i].wh_tc_coef = pow(ar_wheels[i].wh_tc_coef, tc_ratio);
314 float tc_coef = pow(ar_wheels[i].wh_tc_coef, std::min(std::abs(ar_wheels[i].wh_speed) / 5.0f, 1.0f));
315 ar_wheels[i].wh_torque *= tc_coef;
316 m_tractioncontrol =
true;
320 ar_wheels[i].wh_tc_coef = 1.0f;
323 if (ar_wheels[i].wh_braking != WheelBraking::NONE)
326 float abrake = ar_brake_force * ar_brake;
330 if (ar_parking_brake && (ar_wheels[i].wh_braking != WheelBraking::FOOT_ONLY))
332 hbrake = m_handbrake_force;
337 if ((ar_wheels[i].wh_speed < 20.0f)
338 && (((ar_wheels[i].wh_braking == WheelBraking::FOOT_HAND_SKID_LEFT) && (ar_hydro_dir_state > 0.0f))
339 || ((ar_wheels[i].wh_braking == WheelBraking::FOOT_HAND_SKID_RIGHT) && (ar_hydro_dir_state < 0.0f))))
341 dbrake = ar_brake_force * abs(ar_hydro_dir_state);
344 if (abrake != 0.0 || dbrake != 0.0 || hbrake != 0.0)
346 float adbrake = abrake + dbrake;
349 if (alb_mode && curspeed > alb_minspeed && curspeed > fabs(ar_wheels[i].wh_speed) && (adbrake > 0.0f) && wheel_slip > 0.25f)
353 ar_wheels[i].wh_alb_coef = fabs(ar_wheels[i].wh_speed) / curspeed;
354 ar_wheels[i].wh_alb_coef = pow(ar_wheels[i].wh_alb_coef, alb_ratio);
356 adbrake *= ar_wheels[i].wh_alb_coef;
357 m_antilockbrake =
true;
360 float force = -ar_wheels[i].wh_avg_speed * ar_wheels[i].wh_radius * ar_wheels[i].wh_mass /
PHYSICS_DT;
361 force -= ar_wheels[i].wh_last_retorque;
363 if (ar_wheels[i].wh_speed > 0)
364 ar_wheels[i].wh_torque += Math::Clamp(force, -(adbrake + hbrake), 0.0f);
366 ar_wheels[i].wh_torque += Math::Clamp(force, 0.0f, +(adbrake + hbrake));
370 ar_wheels[i].wh_alb_coef = 1.0f;
374 ar_wheels[i].debug_torque += ar_wheels[i].wh_torque / (float)num_steps;
377 Vector3 axis = (ar_wheels[i].wh_axis_node_1->RelPosition - ar_wheels[i].wh_axis_node_0->RelPosition).normalisedCopy();
378 float axis_precalc = ar_wheels[i].wh_torque / (Real)(ar_wheels[i].wh_num_nodes);
380 float expected_wheel_speed = ar_wheels[i].wh_speed;
381 ar_wheels[i].wh_speed = 0.0f;
383 Real contact_counter = 0.0f;
384 Vector3 slip = Vector3::ZERO;
385 Vector3 force = Vector3::ZERO;
386 for (
int j = 0; j < ar_wheels[i].wh_num_nodes; j++)
388 node_t* outer_node = ar_wheels[i].wh_nodes[j];
389 node_t* inner_node = (j % 2) ? ar_wheels[i].wh_axis_node_1 : ar_wheels[i].wh_axis_node_0;
392 float inverted_rlen = 1.0f / radius.length();
394 if (ar_wheels[i].wh_propulsed == WheelPropulsion::BACKWARD)
399 Vector3 dir = axis.crossProduct(radius) * inverted_rlen;
400 ar_wheels[i].wh_nodes[j]->Forces += dir * axis_precalc * inverted_rlen;
401 ar_wheels[i].wh_speed += (outer_node->
Velocity - inner_node->
Velocity).dotProduct(dir);
403 if (ar_wheels[i].wh_nodes[j]->nd_has_ground_contact || ar_wheels[i].wh_nodes[j]->nd_has_mesh_contact)
405 contact_counter += 1.0f;
406 float force_ratio = ar_wheels[i].wh_nodes[j]->nd_last_collision_force.length();
407 slip += ar_wheels[i].wh_nodes[j]->nd_last_collision_slip * force_ratio;
408 force += ar_wheels[i].wh_nodes[j]->nd_last_collision_force;
411 if (contact_counter > 0.0f && !force.isZeroLength())
413 slip /= force.length();
414 slip /= contact_counter;
415 force /= contact_counter;
416 Vector3 normal = force.normalisedCopy();
417 Vector3 v = ar_wheels[i].wh_axis_node_0->Velocity.midPoint(ar_wheels[i].wh_axis_node_1->Velocity);
418 Vector3 vel = v - v.dotProduct(normal) * normal;
419 ar_wheels[i].debug_vel += vel / (float)num_steps;
420 ar_wheels[i].debug_slip += slip / (float)num_steps;
421 ar_wheels[i].debug_force += force / (float)num_steps;
424 ar_wheels[i].wh_speed /= (Real)ar_wheels[i].wh_num_nodes;
425 ar_wheels[i].wh_net_rp += (ar_wheels[i].wh_speed / ar_wheels[i].wh_radius) *
PHYSICS_DT;
427 ar_wheels[i].wh_avg_speed = ar_wheels[i].wh_avg_speed * 0.99 + ar_wheels[i].wh_speed * 0.1;
428 ar_wheels[i].debug_rpm +=
RAD_PER_SEC_TO_RPM * ar_wheels[i].wh_speed / ar_wheels[i].wh_radius / (float)num_steps;
429 if (ar_wheels[i].wh_propulsed == WheelPropulsion::FORWARD)
431 float speedacc = ar_wheels[i].wh_speed / (float)m_num_proped_wheels;
432 ar_wheel_speed += speedacc;
433 ar_wheel_spin += speedacc / ar_wheels[i].wh_radius;
436 expected_wheel_speed += ((ar_wheels[i].wh_last_torque / ar_wheels[i].wh_radius) / ar_wheels[i].wh_mass) *
PHYSICS_DT;
437 ar_wheels[i].wh_last_retorque = ar_wheels[i].wh_mass * (ar_wheels[i].wh_speed - expected_wheel_speed) /
PHYSICS_DT;
440 Vector3 rradius = ar_wheels[i].wh_arm_node->RelPosition - ar_wheels[i].wh_near_attach_node->RelPosition;
441 Vector3 radius = Plane(axis, ar_wheels[i].wh_near_attach_node->RelPosition).projectVector(rradius);
442 float offset = (rradius - radius).length();
443 Real rlen = radius.normalise();
445 if (rlen > 0.01 && offset * 2.0f < rlen && fabs(ar_wheels[i].wh_torque) > 0.01f)
447 Vector3 cforce = axis.crossProduct(radius);
449 cforce *= (0.5f * ar_wheels[i].wh_torque / rlen) * (1.0f - ((offset * 2.0f) / rlen));
450 ar_wheels[i].wh_arm_node->Forces -= cforce;
451 ar_wheels[i].wh_near_attach_node->Forces += cforce;
452 ar_wheels[i].debug_scaled_cforce += cforce / ar_total_mass / (float)num_steps;
455 ar_wheels[i].wh_last_torque = ar_wheels[i].wh_torque;
456 ar_wheels[i].wh_torque = 0.0f;
459 ar_avg_wheel_speed = ar_avg_wheel_speed * 0.995 + ar_wheel_speed * 0.005;
468 if (!m_antilockbrake)
477 if (!m_tractioncontrol)
488 float distance_driven = fabs(ar_wheel_speed *
PHYSICS_DT);
489 m_odometer_total += distance_driven;
490 m_odometer_user += distance_driven;
493 void Actor::CalcShocks(
bool doUpdate,
int num_steps)
496 if (this->ar_has_active_shocks && m_stabilizer_shock_request)
498 if ((m_stabilizer_shock_request == 1 && m_stabilizer_shock_ratio < 0.1) || (m_stabilizer_shock_request == -1 && m_stabilizer_shock_ratio > -0.1))
499 m_stabilizer_shock_ratio = m_stabilizer_shock_ratio + (float)m_stabilizer_shock_request *
PHYSICS_DT *
STAB_RATE;
500 for (
int i = 0; i < ar_num_shocks; i++)
504 ar_beams[ar_shocks[i].beamid].L = ar_beams[ar_shocks[i].beamid].refL * (1.0 + m_stabilizer_shock_ratio);
506 ar_beams[ar_shocks[i].beamid].L = ar_beams[ar_shocks[i].beamid].refL * (1.0 - m_stabilizer_shock_ratio);
510 if (this->ar_has_active_shocks && doUpdate)
512 m_stabilizer_shock_sleep -=
PHYSICS_DT * num_steps;
514 float roll = asin(GetCameraRoll().dotProduct(Vector3::UNIT_Y));
516 if (fabs(roll) > 0.2)
518 m_stabilizer_shock_sleep = -1.0;
520 if (fabs(roll) > 0.01 && m_stabilizer_shock_sleep < 0.0)
522 if (roll > 0.0 && m_stabilizer_shock_request != -1)
524 m_stabilizer_shock_request = 1;
526 else if (roll < 0.0 && m_stabilizer_shock_request != 1)
528 m_stabilizer_shock_request = -1;
532 m_stabilizer_shock_request = 0;
533 m_stabilizer_shock_sleep = 3.0;
538 m_stabilizer_shock_request = 0;
541 if (m_stabilizer_shock_request && fabs(m_stabilizer_shock_ratio) < 0.1)
548 void Actor::CalcHydros()
551 if (ar_hydro_dir_state != 0 || ar_hydro_dir_command != 0)
553 if (!ar_hydro_speed_coupling)
558 float diff = ar_hydro_dir_command - ar_hydro_dir_state;
559 float rate = std::exp(-std::min(std::abs(diff), 1.0f) / sensitivity) * diff;
560 ar_hydro_dir_state += (10.0f / smoothing) *
PHYSICS_DT * rate;
564 if (ar_hydro_dir_command != 0)
568 float rate = std::max(1.2f, 30.0f / (10.0f));
569 if (ar_hydro_dir_state > ar_hydro_dir_command)
577 float rate = std::max(1.2f, 30.0f / (10.0f + std::abs(ar_wheel_speed / 2.0f)));
578 if (ar_hydro_dir_state > ar_hydro_dir_command)
585 if (ar_hydro_dir_state > dirdelta)
586 ar_hydro_dir_state -= dirdelta;
587 else if (ar_hydro_dir_state < -dirdelta)
588 ar_hydro_dir_state += dirdelta;
590 ar_hydro_dir_state = 0;
594 if (ar_hydro_aileron_state != 0 || ar_hydro_aileron_command != 0)
596 if (ar_hydro_aileron_command != 0)
598 if (ar_hydro_aileron_state > ar_hydro_aileron_command)
604 if (ar_hydro_aileron_state > delta)
605 ar_hydro_aileron_state -= delta;
606 else if (ar_hydro_aileron_state < -delta)
607 ar_hydro_aileron_state += delta;
609 ar_hydro_aileron_state = 0;
612 if (ar_hydro_rudder_state != 0 || ar_hydro_rudder_command != 0)
614 if (ar_hydro_rudder_command != 0)
616 if (ar_hydro_rudder_state > ar_hydro_rudder_command)
623 if (ar_hydro_rudder_state > delta)
624 ar_hydro_rudder_state -= delta;
625 else if (ar_hydro_rudder_state < -delta)
626 ar_hydro_rudder_state += delta;
628 ar_hydro_rudder_state = 0;
631 if (ar_hydro_elevator_state != 0 || ar_hydro_elevator_command != 0)
633 if (ar_hydro_elevator_command != 0)
635 if (ar_hydro_elevator_state > ar_hydro_elevator_command)
641 if (ar_hydro_elevator_state > delta)
642 ar_hydro_elevator_state -= delta;
643 else if (ar_hydro_elevator_state < -delta)
644 ar_hydro_elevator_state += delta;
646 ar_hydro_elevator_state = 0;
649 const int num_hydros =
static_cast<int>(ar_hydros.size());
650 for (
int i = 0; i < num_hydros; ++i)
660 if (ar_wheel_speed < 12.0f)
661 cstate += ar_hydro_dir_state * (12.0f - ar_wheel_speed) / 12.0f;
666 cstate += ar_hydro_dir_state;
671 cstate += ar_hydro_aileron_state;
676 cstate += ar_hydro_rudder_state;
681 cstate += ar_hydro_elevator_state;
686 cstate -= ar_hydro_aileron_state;
691 cstate -= ar_hydro_rudder_state;
696 cstate -= ar_hydro_elevator_state;
710 this->CalcAnimators(hydrobeam, cstate, div);
716 cstate /= (float)div;
721 ar_hydro_dir_wheel_display = cstate;
723 float factor = 1.0 - cstate * hydrobeam.
hb_speed;
728 if (factor < 1.0f - ar_beams[beam_idx].shortbound)
729 factor = 1.0f - ar_beams[beam_idx].shortbound;
730 if (factor > 1.0f + ar_beams[beam_idx].longbound)
731 factor = 1.0f + ar_beams[beam_idx].longbound;
739 void Actor::CalcCommands(
bool doUpdate)
741 if (m_has_command_beams)
744 bool requested =
false;
749 ar_engine_hydraulics_ready = ar_engine->getRPM() > ar_engine->getIdleRPM() * 0.95f;
751 ar_engine_hydraulics_ready =
true;
754 float crankfactor = 1.0f;
756 crankfactor = ar_engine->getCrankFactor();
764 for (
int j = 0; j < (int)ar_command_key[i].beams.size(); j++)
766 ar_command_key[i].beams[j].cmb_state->auto_move_lock =
false;
772 float oldValue = ar_command_key[i].commandValue;
774 ar_command_key[i].commandValue = std::max(ar_command_key[i].playerInputValue, ar_command_key[i].triggerInputValue);
776 ar_command_key[i].triggerInputValue = 0.0f;
778 if (ar_command_key[i].commandValue > 0.01f && oldValue < 0.01f)
781 ar_command_key[i].commandValueState = 1;
783 else if (ar_command_key[i].commandValue < 0.01f && oldValue > 0.01f)
786 ar_command_key[i].commandValueState = -1;
789 for (
int j = 0; j < (int)ar_command_key[i].beams.size(); j++)
791 if (ar_command_key[i].commandValue >= 0.5)
793 ar_command_key[i].beams[j].cmb_state->auto_move_lock =
true;
794 if (ar_command_key[i].beams[j].cmb_is_autocentering)
796 ar_command_key[i].beams[j].cmb_state->auto_moving_mode = 0;
805 bool requestpower =
false;
806 for (
int j = 0; j < (int)ar_command_key[i].beams.size(); j++)
812 if (bbeam > ar_num_beams)
817 crankfactor = std::min(crankfactor, 1.0f);
819 float v = ar_command_key[i].commandValue;
820 int& vst = ar_command_key[i].commandValueState;
826 if (ar_beams[bbeam].refL == 0 || ar_beams[bbeam].L == 0)
829 float current = (ar_beams[bbeam].L / ar_beams[bbeam].refL);
834 cmd_beam.
cmb_state->auto_moving_mode = 0;
838 int mode = cmd_beam.
cmb_state->auto_moving_mode;
842 cmd_beam.
cmb_state->auto_moving_mode = -1;
844 cmd_beam.
cmb_state->auto_moving_mode = 1;
847 if (mode != 0 && mode != cmd_beam.
cmb_state->auto_moving_mode)
850 cmd_beam.
cmb_state->auto_moving_mode = 0;
855 if (ar_beams[bbeam].refL != 0 && ar_beams[bbeam].L != 0)
857 float clen = ar_beams[bbeam].L / ar_beams[bbeam].refL;
860 float dl = ar_beams[bbeam].L;
867 cmd_beam.
cmb_state->pressed_center_mode =
true;
868 cmd_beam.
cmb_state->auto_moving_mode = 0;
872 cmd_beam.
cmb_state->pressed_center_mode =
false;
877 bool key = (v > 0.5);
878 if (bbeam_dir * cmd_beam.
cmb_state->auto_moving_mode <= 0 && key)
880 cmd_beam.
cmb_state->auto_moving_mode = bbeam_dir * 1;
882 else if (cmd_beam.
cmb_state->auto_moving_mode == bbeam_dir * 1 && !key)
884 cmd_beam.
cmb_state->auto_moving_mode = bbeam_dir * 2;
886 else if (cmd_beam.
cmb_state->auto_moving_mode == bbeam_dir * 2 && key)
888 cmd_beam.
cmb_state->auto_moving_mode = bbeam_dir * 3;
890 else if (cmd_beam.
cmb_state->auto_moving_mode == bbeam_dir * 3 && !key)
892 cmd_beam.
cmb_state->auto_moving_mode = 0;
896 v = ar_command_key[i].command_inertia.CalcCmdKeyDelay(v,
PHYSICS_DT);
898 if (bbeam_dir * cmd_beam.
cmb_state->auto_moving_mode > 0)
901 if (cmd_beam.
cmb_needs_engine && ((ar_engine && !ar_engine->isRunning()) || !ar_engine_hydraulics_ready))
941 dl = fabs(dl - ar_beams[bbeam].L);
951 cmd_beam.
cmb_state->auto_moving_mode = 0;
956 for (
int j = 0; j < (int)ar_command_key[i].rotators.size(); j++)
959 int rota = std::abs(ar_command_key[i].rotators[j]) - 1;
961 if (ar_rotators[rota].needs_engine && ((ar_engine && !ar_engine->isRunning()) || !ar_engine_hydraulics_ready))
964 v = ar_command_key[i].rotator_inertia.CalcCmdKeyDelay(ar_command_key[i].commandValue,
PHYSICS_DT);
966 if (v > 0.0f && ar_rotators[rota].engine_coupling > 0.0f)
971 if (ar_rotators[rota].engine_coupling > 0.0f)
974 if (ar_command_key[i].rotators[j] > 0)
975 ar_rotators[rota].angle += ar_rotators[rota].rate * v * cf *
PHYSICS_DT;
977 ar_rotators[rota].angle -= ar_rotators[rota].rate * v * cf *
PHYSICS_DT;
979 if (doUpdate || v != 0.0f)
981 ar_rotators[rota].debug_rate = ar_rotators[rota].rate * v * cf;
990 ar_engine->setHydroPump(work);
991 ar_engine->setPrime(requested);
1000 float pump_rpm = 660.0f * (1.0f - (work / (float)active) / 100.0f);
1010 for (
int i = 0; i < ar_num_rotators; i++)
1013 Vector3 ax1 = ar_nodes[ar_rotators[i].axis1].RelPosition;
1014 Vector3 ax2 = ar_nodes[ar_rotators[i].axis2].RelPosition;
1015 Vector3 axis = ax1 - ax2;
1018 Plane pl = Plane(axis, 0);
1020 ar_rotators[i].debug_aerror = 0;
1021 for (
int k = 0; k < 2; k++)
1024 Vector3 ref1 = pl.projectVector(ax1 - ar_nodes[ar_rotators[i].nodes1[k]].RelPosition);
1025 Vector3 ref2 = pl.projectVector(ax2 - ar_nodes[ar_rotators[i].nodes2[k]].RelPosition);
1026 float ref1len = ref1.normalise();
1027 float ref2len = ref2.normalise();
1029 Vector3 th1 = Quaternion(Radian(ar_rotators[i].angle + Math::HALF_PI), axis) * ref1;
1031 float aerror = asin(th1.dotProduct(ref2));
1032 ar_rotators[i].debug_aerror += 0.5f * aerror;
1034 float rigidity = ar_rotators[i].force;
1035 Vector3 dir1 = ref1.crossProduct(axis);
1036 Vector3 dir2 = ref2.crossProduct(axis);
1039 if (ref1len <= ar_rotators[i].tolerance)
1041 if (ref2len <= ar_rotators[i].tolerance)
1044 ar_nodes[ar_rotators[i].nodes1[k ]].Forces += (aerror * ref1len * rigidity) * dir1;
1045 ar_nodes[ar_rotators[i].nodes2[k ]].Forces -= (aerror * ref2len * rigidity) * dir2;
1047 ar_nodes[ar_rotators[i].nodes1[k + 2]].Forces -= (aerror * ref1len * rigidity) * dir1;
1048 ar_nodes[ar_rotators[i].nodes2[k + 2]].Forces += (aerror * ref2len * rigidity) * dir2;
1054 void Actor::CalcTies()
1057 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
1064 if (it->ti_beam->refL == 0 || it->ti_beam->L == 0)
1067 float clen = it->ti_beam->L / it->ti_beam->refL;
1068 if (clen > it->ti_min_length)
1070 it->ti_beam->L *= (1.0 - it->ti_contract_speed *
PHYSICS_DT / it->ti_beam->L);
1075 it->ti_tying =
false;
1079 if (fabs(it->ti_beam->stress) > it->ti_max_stress)
1081 it->ti_tying =
false;
1085 void Actor::CalcTruckEngine(
bool doUpdate)
1089 ar_engine->UpdateEngine(
PHYSICS_DT, doUpdate);
1093 void Actor::CalcReplay()
1095 if (m_replay_handler && m_replay_handler->isValid())
1097 m_replay_handler->onPhysicsStep();
1101 bool Actor::CalcForcesEulerPrepare(
bool doUpdate)
1103 if (m_ongoing_reset)
1105 if (ar_physics_paused)
1107 if (ar_state != ActorState::LOCAL_SIMULATED)
1114 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
1129 msg <<
" (index: " << node->
pos <<
")";
1135 msg <<
"It was between nodes ";
1142 void Actor::CalcBeams(
bool trigger_hooks)
1144 for (
int i = 0; i < ar_num_beams; i++)
1146 if (!ar_beams[i].bm_disabled && !ar_beams[i].bm_inter_actor)
1149 Vector3 dis = ar_beams[i].p1->RelPosition - ar_beams[i].p2->RelPosition;
1151 Real dislen = dis.squaredLength();
1154 dislen *= inverted_dislen;
1157 Real difftoBeamL = dislen - ar_beams[i].L;
1159 Real k = ar_beams[i].k;
1160 Real d = ar_beams[i].d;
1163 float v = (ar_beams[i].p1->Velocity - ar_beams[i].p2->Velocity).dotProduct(dis) * inverted_dislen;
1165 if (ar_beams[i].bounded ==
SHOCK1)
1167 float interp_ratio = 0.0f;
1170 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
1171 interp_ratio = difftoBeamL - ar_beams[i].longbound * ar_beams[i].L;
1172 else if (difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
1173 interp_ratio = -difftoBeamL - ar_beams[i].shortbound * ar_beams[i].L;
1175 if (interp_ratio != 0.0f)
1184 tspring = ar_beams[i].shock->sbd_spring;
1185 tdamp = ar_beams[i].shock->sbd_damp;
1188 k += (tspring - k) * interp_ratio;
1189 d += (tdamp - d) * interp_ratio;
1192 else if (ar_beams[i].bounded ==
TRIGGER)
1194 this->CalcTriggers(i, difftoBeamL, trigger_hooks);
1196 else if (ar_beams[i].bounded ==
SHOCK2)
1198 this->CalcShocks2(i, difftoBeamL, k, d, v);
1200 else if (ar_beams[i].bounded ==
SHOCK3)
1202 this->CalcShocks3(i, difftoBeamL, k, d, v);
1206 if (difftoBeamL > 0.0f)
1211 if (ar_beams[i].longbound > 0.0f)
1214 break_limit = ar_beams[i].longbound;
1218 if (difftoBeamL > ar_beams[i].L * break_limit)
1220 ar_beams[i].bm_broken =
true;
1221 ar_beams[i].bm_disabled =
true;
1222 if (m_beam_break_debug_enabled)
1225 msg <<
"[RoR|Diag] XXX Support-Beam " << i <<
" limit extended and broke. "
1226 <<
"Length: " << difftoBeamL <<
" / max. Length: " << (ar_beams[i].L*break_limit) <<
". ";
1233 else if (ar_beams[i].bounded ==
ROPE)
1235 if (difftoBeamL < 0.0f)
1242 if (trigger_hooks && ar_beams[i].bounded && ar_beams[i].bm_type ==
BEAM_HYDRO)
1244 ar_beams[i].debug_k = k * std::abs(difftoBeamL);
1245 ar_beams[i].debug_d = d * std::abs(v);
1246 ar_beams[i].debug_v = std::abs(v);
1249 float slen = -k * difftoBeamL - d * v;
1250 ar_beams[i].stress = slen;
1253 float len = std::abs(slen);
1254 if (len > ar_beams[i].minmaxposnegstress)
1256 if (ar_beams[i].bm_type ==
BEAM_NORMAL && ar_beams[i].bounded !=
SHOCK1 && k != 0.0f)
1259 if (slen > ar_beams[i].maxposstress && difftoBeamL < 0.0f)
1261 Real yield_length = ar_beams[i].maxposstress / k;
1262 Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef);
1263 Real Lold = ar_beams[i].L;
1264 ar_beams[i].L += deform;
1266 slen = slen - (slen - ar_beams[i].maxposstress) * 0.5f;
1268 if (ar_beams[i].L > 0.0f && Lold > ar_beams[i].L)
1270 ar_beams[i].maxposstress *= Lold / ar_beams[i].L;
1271 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].maxposstress, -ar_beams[i].maxnegstress);
1272 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].minmaxposnegstress, ar_beams[i].strength);
1277 if (m_beam_deform_debug_enabled)
1280 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1281 << len <<
" / " << ar_beams[i].strength <<
". ";
1286 else if (slen < ar_beams[i].maxnegstress && difftoBeamL > 0.0f)
1288 Real yield_length = ar_beams[i].maxnegstress / k;
1289 Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef);
1290 Real Lold = ar_beams[i].L;
1291 ar_beams[i].L += deform;
1292 slen = slen - (slen - ar_beams[i].maxnegstress) * 0.5f;
1294 if (Lold > 0.0f && ar_beams[i].L > Lold)
1296 ar_beams[i].maxnegstress *= ar_beams[i].L / Lold;
1297 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].maxposstress, -ar_beams[i].maxnegstress);
1298 ar_beams[i].minmaxposnegstress = std::min(ar_beams[i].minmaxposnegstress, ar_beams[i].strength);
1300 ar_beams[i].strength -= deform * k;
1301 if (m_beam_deform_debug_enabled)
1304 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1305 << len <<
" / " << ar_beams[i].strength <<
". ";
1313 if (len > ar_beams[i].strength)
1323 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)))
1326 ar_beams[i].bm_broken =
true;
1327 ar_beams[i].bm_disabled =
true;
1329 if (m_beam_break_debug_enabled)
1332 msg <<
"[RoR|Diag] XXX Beam " << i <<
" just broke with force " << len <<
" / " << ar_beams[i].strength <<
". ";
1339 if (ar_beams[i].detacher_group > 0)
1342 for (
int j = 0; j < ar_num_beams; j++)
1346 if (abs(ar_beams[j].detacher_group) == ar_beams[i].detacher_group)
1348 ar_beams[j].bm_broken =
true;
1349 ar_beams[j].bm_disabled =
true;
1350 if (m_beam_break_debug_enabled)
1353 "Deleting Detacher BeamID: " +
TOSTRING(j) +
", Detacher Group: " +
TOSTRING(ar_beams[i].detacher_group)+
", actor ID: " +
TOSTRING(ar_instance_id));
1360 if (wheeldetacher.wd_detacher_group == ar_beams[i].detacher_group)
1362 ar_wheels[wheeldetacher.wd_wheel_id].wh_is_detached =
true;
1363 if (m_beam_break_debug_enabled)
1366 "Detaching wheel ID: " +
TOSTRING(wheeldetacher.wd_wheel_id) +
", Detacher Group: " +
TOSTRING(ar_beams[i].detacher_group)+
", actor ID: " +
TOSTRING(ar_instance_id));
1374 ar_beams[i].strength = 2.0f * ar_beams[i].minmaxposnegstress;
1378 for (
int mk = 0; mk < ar_num_buoycabs; mk++)
1380 int tmpv = ar_buoycabs[mk] * 3;
1381 if (ar_buoycab_types[mk] == Buoyance::BUOY_DRAGONLY)
1383 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]]) &&
1384 (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]]))
1386 m_buoyance->sink =
true;
1394 f *= (slen * inverted_dislen);
1395 ar_beams[i].p1->Forces += f;
1396 ar_beams[i].p2->Forces -= f;
1401 void Actor::CalcBeamsInterActor()
1403 for (
int i = 0; i < static_cast<int>(ar_inter_beams.size()); i++)
1405 if (!ar_inter_beams[i]->bm_disabled && ar_inter_beams[i]->bm_inter_actor)
1408 Vector3 dis = ar_inter_beams[i]->p1->AbsPosition - ar_inter_beams[i]->p2->AbsPosition;
1410 Real dislen = dis.squaredLength();
1413 dislen *= inverted_dislen;
1416 Real difftoBeamL = dislen - ar_inter_beams[i]->L;
1418 Real k = ar_inter_beams[i]->k;
1419 Real d = ar_inter_beams[i]->d;
1421 if (ar_inter_beams[i]->bounded ==
ROPE && difftoBeamL < 0.0f)
1428 Vector3 v = ar_inter_beams[i]->p1->Velocity - ar_inter_beams[i]->p2->Velocity;
1430 float slen = -k * (difftoBeamL) - d * v.dotProduct(dis) * inverted_dislen;
1431 ar_inter_beams[i]->stress = slen;
1434 float len = std::abs(slen);
1435 if (len > ar_inter_beams[i]->minmaxposnegstress)
1437 if (ar_inter_beams[i]->bm_type ==
BEAM_NORMAL && ar_inter_beams[i]->bounded !=
SHOCK1 && k != 0.0f)
1440 if (slen > ar_inter_beams[i]->maxposstress && difftoBeamL < 0.0f)
1442 Real yield_length = ar_inter_beams[i]->maxposstress / k;
1443 Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef);
1444 Real Lold = ar_inter_beams[i]->L;
1445 ar_inter_beams[i]->L += deform;
1446 ar_inter_beams[i]->L = std::max(
MIN_BEAM_LENGTH, ar_inter_beams[i]->L);
1447 slen = slen - (slen - ar_inter_beams[i]->maxposstress) * 0.5f;
1449 if (ar_inter_beams[i]->L > 0.0f && Lold > ar_inter_beams[i]->L)
1451 ar_inter_beams[i]->maxposstress *= Lold / ar_inter_beams[i]->L;
1452 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress);
1453 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength);
1458 if (m_beam_deform_debug_enabled)
1461 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1462 << len <<
" / " << ar_inter_beams[i]->strength <<
". ";
1467 else if (slen < ar_inter_beams[i]->maxnegstress && difftoBeamL > 0.0f)
1469 Real yield_length = ar_inter_beams[i]->maxnegstress / k;
1470 Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef);
1471 Real Lold = ar_inter_beams[i]->L;
1472 ar_inter_beams[i]->L += deform;
1473 slen = slen - (slen - ar_inter_beams[i]->maxnegstress) * 0.5f;
1475 if (Lold > 0.0f && ar_inter_beams[i]->L > Lold)
1477 ar_inter_beams[i]->maxnegstress *= ar_inter_beams[i]->L / Lold;
1478 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress);
1479 ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength);
1481 ar_inter_beams[i]->strength -= deform * k;
1482 if (m_beam_deform_debug_enabled)
1485 msg <<
"[RoR|Diag] YYY Beam " << i <<
" just deformed with extension force "
1486 << len <<
" / " << ar_inter_beams[i]->strength <<
". ";
1494 if (len > ar_inter_beams[i]->strength)
1504 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)))
1507 ar_inter_beams[i]->bm_broken =
true;
1508 ar_inter_beams[i]->bm_disabled =
true;
1510 if (m_beam_break_debug_enabled)
1513 msg <<
"Beam " << i <<
" just broke with force " << len <<
" / " << ar_inter_beams[i]->strength <<
". ";
1520 ar_inter_beams[i]->strength = 2.0f * ar_inter_beams[i]->minmaxposnegstress;
1527 f *= (slen * inverted_dislen);
1528 ar_inter_beams[i]->p1->Forces += f;
1529 ar_inter_beams[i]->p2->Forces -= f;
1534 void Actor::CalcNodes()
1538 m_water_contact =
false;
1540 for (
NodeNum_t i = 0; i < ar_num_nodes; i++)
1543 if (!ar_nodes[i].nd_no_ground_contact)
1545 Vector3 oripos = ar_nodes[i].AbsPosition;
1548 ar_nodes[i].nd_has_ground_contact = contacted;
1549 if (ar_nodes[i].nd_has_ground_contact || ar_nodes[i].nd_has_mesh_contact)
1551 ar_last_fuzzy_ground_model = ar_nodes[i].nd_last_collision_gm;
1555 ar_nodes[i].RelPosition += ar_nodes[i].AbsPosition - oripos;
1559 if (i == ar_main_camera_node_pos)
1562 m_camera_gforces_accu += ar_nodes[i].Forces / ar_nodes[i].mass;
1566 if (!ar_nodes[i].nd_immovable)
1568 ar_nodes[i].Velocity += ar_nodes[i].Forces / ar_nodes[i].mass *
PHYSICS_DT;
1569 ar_nodes[i].RelPosition += ar_nodes[i].Velocity *
PHYSICS_DT;
1570 ar_nodes[i].AbsPosition = ar_origin;
1571 ar_nodes[i].AbsPosition += ar_nodes[i].RelPosition;
1577 ar_nodes[i].Forces = Vector3(0, ar_nodes[i].mass * gravity, 0);
1579 Real approx_speed =
approx_sqrt(ar_nodes[i].Velocity.squaredLength());
1582 if (approx_speed > 6860 && !m_ongoing_reset)
1586 rq->
amr_type = ActorModifyRequest::Type::RESET_ON_SPOT;
1588 m_ongoing_reset =
true;
1591 if (m_fusealge_airfoil)
1594 ar_nodes[i].Forces += ar_fusedrag;
1596 else if (!ar_disable_aerodyn_turbulent_drag)
1600 Vector3 drag = -defdragxspeed * ar_nodes[i].Velocity;
1602 Real maxtur = defdragxspeed * approx_speed * 0.005f;
1604 ar_nodes[i].Forces += drag;
1609 const bool is_under_water = water->IsUnderWater(ar_nodes[i].AbsPosition);
1612 m_water_contact =
true;
1613 if (ar_num_buoycabs == 0)
1616 ar_nodes[i].Forces -= (
DEFAULT_WATERDRAG * approx_speed) * ar_nodes[i].Velocity;
1618 ar_nodes[i].Forces += ar_nodes[i].buoyancy * Vector3::UNIT_Y;
1621 if (i == ar_cinecam_node[0] && ar_engine)
1623 ar_engine->stopEngine();
1626 ar_nodes[i].nd_under_water = is_under_water;
1640 void Actor::CalcEventBoxes()
1649 m_potential_eventboxes.clear();
1655 bool has_collision =
false;
1656 bool do_callback_enter =
true;
1657 bool do_callback_exit =
false;
1658 auto itor = m_active_eventboxes.begin();
1659 while (itor != m_active_eventboxes.end())
1661 if (itor->first == cbox)
1668 itor = m_active_eventboxes.erase(itor);
1670 do_callback_enter =
false;
1671 do_callback_exit =
true;
1684 for (
NodeNum_t i = 0; i < ar_num_nodes; i++)
1689 do_callback_exit =
false;
1691 m_active_eventboxes.push_back(std::make_pair(cbox, i));
1693 if (do_callback_enter)
1710 if (do_callback_exit)
1719 void Actor::CalcHooks()
1722 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
1725 it->hk_timer = std::max(0.0f, it->hk_timer -
PHYSICS_DT);
1727 if (it->hk_lock_node && it->hk_locked ==
PRELOCK)
1729 if (it->hk_beam->L < it->hk_min_length)
1737 if (it->hk_beam->L > it->hk_lockspeed && fabs(it->hk_beam->stress) < it->hk_maxforce)
1739 it->hk_beam->L = (it->hk_beam->L - it->hk_lockspeed);
1743 if (fabs(it->hk_beam->stress) < it->hk_maxforce)
1745 it->hk_beam->L = 0.001f;
1751 if (it->hk_nodisable)
1761 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
1771 void Actor::CalcRopes()
1773 for (
auto r : ar_ropes)
1775 if (r.rp_locked ==
LOCKED && r.rp_locked_ropable)
1777 auto locked_node = r.rp_locked_ropable->node;
1778 r.rp_beam->p2->AbsPosition = locked_node->AbsPosition;
1779 r.rp_beam->p2->RelPosition = locked_node->AbsPosition - ar_origin;
1780 r.rp_beam->p2->Velocity = locked_node->Velocity;
1781 locked_node->Forces += r.rp_beam->p2->Forces;
1782 r.rp_beam->p2->Forces = Vector3::ZERO;