mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
* use std::move() for local variables that are copied but not reused Addresses ~140 Coverity "Variable copied when it could be moved" defects across 74 files. Every std::move() targets a local variable whose value is consumed by push_back, emplace, assignment, lambda capture, or a function call and is never read again afterward. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * clang: use std::make_shared * clang: use std::make_unique * address feedback --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
441 lines
17 KiB
C++
441 lines
17 KiB
C++
#include "model/animation/modelanimation_moveables.h"
|
|
#include "model/animation/modelanimation_segments.h"
|
|
|
|
namespace animation {
|
|
|
|
ModelAnimationMoveableOrientation::ModelAnimationMoveableOrientation(std::shared_ptr<ModelAnimationSubmodel> submodel, const angles& defaultOrient) :
|
|
m_submodel(std::move(submodel)), m_defaultPosOrient(defaultOrient) { }
|
|
|
|
void ModelAnimationMoveableOrientation::update(polymodel_instance* pmi, const SCP_vector<std::any>& args) {
|
|
if(args.size() < 3){
|
|
Error(LOCATION,"Tried updating moveable orientation with too few (%d of 3) arguments!", (int) args.size());
|
|
return;
|
|
}
|
|
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
try {
|
|
auto p = std::any_cast<int>(args[0]), h = std::any_cast<int>(args[1]), b = std::any_cast<int>(args[2]);
|
|
|
|
anim->forceRecalculate(pmi);
|
|
|
|
auto& setOrientation = *std::static_pointer_cast<ModelAnimationSegmentSetOrientation>(anim->m_animation);
|
|
setOrientation.m_targetAngle = angles{fl_radians((float)p), fl_radians((float)b), fl_radians((float)h)};
|
|
|
|
anim->start(pmi, ModelAnimationDirection::FWD);
|
|
}
|
|
catch (const std::bad_any_cast& e){
|
|
Error(LOCATION, "Argument error trying to update orientation moveable: %s", e.what());
|
|
}
|
|
}
|
|
|
|
void ModelAnimationMoveableOrientation::initialize(ModelAnimationSet* parentSet, polymodel_instance* pmi) {
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
anim = std::make_shared<ModelAnimation>(false, false, true, parentSet);
|
|
|
|
anim->setAnimation(std::make_shared<ModelAnimationSegmentSetOrientation>(parentSet->getSubmodel(m_submodel), m_defaultPosOrient, ModelAnimationCoordinateRelation::RELATIVE_COORDS));
|
|
|
|
anim->start(pmi,ModelAnimationDirection::FWD);
|
|
}
|
|
|
|
std::shared_ptr<ModelAnimationMoveable> ModelAnimationMoveableOrientation::parser() {
|
|
required_string("+Angle:");
|
|
angles angle;
|
|
stuff_angles_deg_phb(&angle);
|
|
|
|
auto submodel = ModelAnimationParseHelper::parseSubmodel();
|
|
if(submodel == nullptr)
|
|
error_display(1, "Could not create moveable! Moveable Orientation has no target submodel!");
|
|
|
|
return std::make_shared<ModelAnimationMoveableOrientation>(std::move(submodel), angle);
|
|
}
|
|
|
|
|
|
ModelAnimationMoveableRotation::ModelAnimationMoveableRotation(std::shared_ptr<ModelAnimationSubmodel> submodel, const angles& defaultOrient, const angles& velocity, const std::optional<angles>& acceleration) :
|
|
m_submodel(std::move(submodel)), m_defaultPosOrient(defaultOrient), m_velocity(velocity), m_acceleration(acceleration) { }
|
|
|
|
void ModelAnimationMoveableRotation::update(polymodel_instance* pmi, const SCP_vector<std::any>& args) {
|
|
if(args.size() < 3){
|
|
Error(LOCATION,"Tried updating moveable rotation with too few (%d of 3) arguments!", (int) args.size());
|
|
return;
|
|
}
|
|
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
try {
|
|
auto p = std::any_cast<int>(args[0]), h = std::any_cast<int>(args[1]), b = std::any_cast<int>(args[2]);
|
|
|
|
|
|
auto& sequence = *std::static_pointer_cast<ModelAnimationSegmentSerial>(anim->m_animation);
|
|
auto& setOrientation = *std::static_pointer_cast<ModelAnimationSegmentSetOrientation>(sequence.m_segments[0]);
|
|
auto& rotation = *std::static_pointer_cast<ModelAnimationSegmentRotation>(sequence.m_segments[1]);
|
|
|
|
ModelAnimationSubmodelBuffer buffer;
|
|
buffer[rotation.m_submodel].data.orientation = IDENTITY_MATRIX;
|
|
//Will now only contain the delta of the rotation
|
|
anim->m_animation->calculateAnimation(buffer, anim->getTime(pmi->id), pmi->id);
|
|
|
|
anim->forceRecalculate(pmi);
|
|
|
|
setOrientation.m_targetOrientation = buffer[rotation.m_submodel].data.orientation;
|
|
|
|
rotation.m_targetAngle = angles{fl_radians((float)p), fl_radians((float)b), fl_radians((float)h)};
|
|
|
|
anim->start(pmi, ModelAnimationDirection::FWD);
|
|
}
|
|
catch (const std::bad_any_cast& e){
|
|
Error(LOCATION, "Argument error trying to update rotation moveable: %s", e.what());
|
|
}
|
|
}
|
|
|
|
void ModelAnimationMoveableRotation::initialize(ModelAnimationSet* parentSet, polymodel_instance* pmi) {
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
anim = std::make_shared<ModelAnimation>(false, false, true, parentSet);
|
|
|
|
matrix orient;
|
|
vm_angles_2_matrix(&orient, &m_defaultPosOrient);
|
|
|
|
auto submodel = parentSet->getSubmodel(m_submodel);
|
|
|
|
auto sequence = std::make_shared<ModelAnimationSegmentSerial>();
|
|
sequence->addSegment(std::make_shared<ModelAnimationSegmentSetOrientation>(submodel, orient, ModelAnimationCoordinateRelation::RELATIVE_COORDS));
|
|
sequence->addSegment(std::make_shared<ModelAnimationSegmentRotation>(std::move(submodel), m_defaultPosOrient, m_velocity, std::nullopt, m_acceleration, ModelAnimationCoordinateRelation::ABSOLUTE_COORDS));
|
|
|
|
anim->setAnimation(sequence);
|
|
|
|
anim->start(pmi,ModelAnimationDirection::FWD);
|
|
}
|
|
|
|
std::shared_ptr<ModelAnimationMoveable> ModelAnimationMoveableRotation::parser() {
|
|
required_string("+Angle:");
|
|
angles angle;
|
|
stuff_angles_deg_phb(&angle);
|
|
|
|
required_string("+Velocity:");
|
|
angles velocity;
|
|
stuff_angles_deg_phb(&velocity);
|
|
|
|
std::optional<angles> acceleration;
|
|
if (optional_string("+Acceleration:")) {
|
|
angles parse;
|
|
stuff_angles_deg_phb(&parse);
|
|
acceleration = parse;
|
|
}
|
|
|
|
auto submodel = ModelAnimationParseHelper::parseSubmodel();
|
|
if(submodel == nullptr)
|
|
error_display(1, "Could not create moveable! Moveable Rotation has no target submodel!");
|
|
|
|
return std::make_shared<ModelAnimationMoveableRotation>(std::move(submodel), angle, velocity, acceleration);
|
|
}
|
|
|
|
|
|
ModelAnimationMoveableTranslation::ModelAnimationMoveableTranslation(std::shared_ptr<ModelAnimationSubmodel> submodel, const vec3d& defaultOffset, const vec3d& velocity, const std::optional<vec3d>& acceleration) :
|
|
m_submodel(std::move(submodel)), m_defaultOffset(defaultOffset), m_velocity(velocity), m_acceleration(acceleration) { }
|
|
|
|
void ModelAnimationMoveableTranslation::update(polymodel_instance* pmi, const SCP_vector<std::any>& args) {
|
|
if(args.size() < 3){
|
|
Error(LOCATION,"Tried updating moveable translation with too few (%d of 3) arguments!", (int) args.size());
|
|
return;
|
|
}
|
|
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
try {
|
|
auto x = std::any_cast<int>(args[0]), y = std::any_cast<int>(args[1]), z = std::any_cast<int>(args[2]);
|
|
|
|
|
|
auto& sequence = *std::static_pointer_cast<ModelAnimationSegmentSerial>(anim->m_animation);
|
|
auto& setOffset = *std::static_pointer_cast<ModelAnimationSegmentSetOffset>(sequence.m_segments[0]);
|
|
auto& translation = *std::static_pointer_cast<ModelAnimationSegmentTranslation>(sequence.m_segments[1]);
|
|
|
|
ModelAnimationSubmodelBuffer buffer;
|
|
buffer[translation.m_submodel].data.position = ZERO_VECTOR;
|
|
//Will now only contain the delta of the translation
|
|
anim->m_animation->calculateAnimation(buffer, anim->getTime(pmi->id), pmi->id);
|
|
|
|
anim->forceRecalculate(pmi);
|
|
|
|
setOffset.m_target = buffer[translation.m_submodel].data.position;
|
|
|
|
translation.m_target = vec3d{{{x * 0.01f, y * 0.01f, z * 0.01f}}};
|
|
|
|
anim->start(pmi, ModelAnimationDirection::FWD);
|
|
}
|
|
catch (const std::bad_any_cast& e){
|
|
Error(LOCATION, "Argument error trying to update translation moveable: %s", e.what());
|
|
}
|
|
}
|
|
|
|
void ModelAnimationMoveableTranslation::initialize(ModelAnimationSet* parentSet, polymodel_instance* pmi) {
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
anim = std::make_shared<ModelAnimation>(false, false, true, parentSet);
|
|
|
|
auto submodel = parentSet->getSubmodel(m_submodel);
|
|
|
|
auto sequence = std::make_shared<ModelAnimationSegmentSerial>();
|
|
sequence->addSegment(std::make_shared<ModelAnimationSegmentSetOffset>(submodel, m_defaultOffset, ModelAnimationCoordinateRelation::RELATIVE_COORDS));
|
|
sequence->addSegment(std::make_shared<ModelAnimationSegmentTranslation>(std::move(submodel), m_defaultOffset, m_velocity, std::nullopt, m_acceleration, ModelAnimationSegmentTranslation::CoordinateSystem::COORDS_PARENT, ModelAnimationCoordinateRelation::ABSOLUTE_COORDS));
|
|
|
|
anim->setAnimation(sequence);
|
|
|
|
anim->start(pmi,ModelAnimationDirection::FWD);
|
|
}
|
|
|
|
std::shared_ptr<ModelAnimationMoveable> ModelAnimationMoveableTranslation::parser() {
|
|
required_string("+Target:");
|
|
vec3d angle;
|
|
stuff_vec3d(&angle);
|
|
|
|
required_string("+Velocity:");
|
|
vec3d velocity;
|
|
stuff_vec3d(&velocity);
|
|
|
|
std::optional<vec3d> acceleration;
|
|
if (optional_string("+Acceleration:")) {
|
|
vec3d parse;
|
|
stuff_vec3d(&parse);
|
|
acceleration = parse;
|
|
}
|
|
|
|
auto submodel = ModelAnimationParseHelper::parseSubmodel();
|
|
if(submodel == nullptr)
|
|
error_display(1, "Could not create moveable! Moveable Translation has no target submodel!");
|
|
|
|
return std::make_shared<ModelAnimationMoveableTranslation>(std::move(submodel), angle, velocity, acceleration);
|
|
}
|
|
|
|
|
|
ModelAnimationMoveableAxisRotation::ModelAnimationMoveableAxisRotation(std::shared_ptr<ModelAnimationSubmodel> submodel, const float& velocity, const std::optional<float>& acceleration, const vec3d& axis) :
|
|
m_submodel(std::move(submodel)), m_velocity(velocity), m_acceleration(acceleration), m_axis(axis) { }
|
|
|
|
void ModelAnimationMoveableAxisRotation::update(polymodel_instance* pmi, const SCP_vector<std::any>& args) {
|
|
if(args.empty()){
|
|
Error(LOCATION,"Tried updating moveable axis rotation with too few (%d of 1) arguments!", (int) args.size());
|
|
return;
|
|
}
|
|
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
try {
|
|
auto ang = std::any_cast<int>(args[0]);
|
|
|
|
auto& sequence = *std::static_pointer_cast<ModelAnimationSegmentSerial>(anim->m_animation);
|
|
auto& setOrientation = *std::static_pointer_cast<ModelAnimationSegmentSetOrientation>(sequence.m_segments[0]);
|
|
auto& rotation = *std::static_pointer_cast<ModelAnimationSegmentAxisRotation>(sequence.m_segments[1]);
|
|
|
|
ModelAnimationSubmodelBuffer buffer;
|
|
buffer[rotation.m_submodel].data.orientation = IDENTITY_MATRIX;
|
|
//Will now only contain the delta of the rotation
|
|
sequence.m_segments[1]->calculateAnimation(buffer, anim->getTime(pmi->id), pmi->id);
|
|
|
|
anim->forceRecalculate(pmi);
|
|
|
|
matrix startOrient = *setOrientation.m_targetOrientation;
|
|
matrix newOrient;
|
|
//Apply rotation to old default state
|
|
vm_matrix_x_matrix(&newOrient, &startOrient, &buffer[rotation.m_submodel].data.orientation);
|
|
setOrientation.m_targetOrientation = newOrient;
|
|
|
|
float currentAngle;
|
|
vm_closest_angle_to_matrix(&newOrient, &m_axis, ¤tAngle);
|
|
//CurrentAngle is 0 to 2Pi, convert to -pi to pi
|
|
if (currentAngle > PI)
|
|
currentAngle -= PI2;
|
|
|
|
rotation.m_targetAngle = fl_radians((float)ang) - currentAngle;
|
|
|
|
anim->start(pmi, ModelAnimationDirection::FWD);
|
|
}
|
|
catch(const std::bad_any_cast& e){
|
|
Error(LOCATION, "Argument error trying to update rotation moveable: %s", e.what());
|
|
}
|
|
}
|
|
|
|
void ModelAnimationMoveableAxisRotation::initialize(ModelAnimationSet* parentSet, polymodel_instance* pmi) {
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
anim = std::make_shared<ModelAnimation>(false, false, true, parentSet);
|
|
|
|
auto submodel = parentSet->getSubmodel(m_submodel);
|
|
|
|
auto sequence = std::make_shared<ModelAnimationSegmentSerial>();
|
|
sequence->addSegment(std::make_shared<ModelAnimationSegmentSetOrientation>(submodel, vmd_identity_matrix, ModelAnimationCoordinateRelation::RELATIVE_COORDS));
|
|
sequence->addSegment(std::make_shared<ModelAnimationSegmentAxisRotation>(std::move(submodel), 0.0f, m_velocity, std::nullopt, m_acceleration, m_axis));
|
|
|
|
anim->setAnimation(sequence);
|
|
|
|
anim->start(pmi,ModelAnimationDirection::FWD);
|
|
}
|
|
|
|
std::shared_ptr<ModelAnimationMoveable> ModelAnimationMoveableAxisRotation::parser() {
|
|
required_string("+Axis:");
|
|
vec3d axis;
|
|
stuff_vec3d(&axis);
|
|
|
|
required_string("+Velocity:");
|
|
float velocity;
|
|
stuff_float(&velocity);
|
|
velocity = fl_radians(velocity);
|
|
|
|
std::optional<float> acceleration;
|
|
if (optional_string("+Acceleration:")) {
|
|
float parse;
|
|
stuff_float(&parse);
|
|
acceleration = fl_radians(parse);
|
|
}
|
|
|
|
auto submodel = ModelAnimationParseHelper::parseSubmodel();
|
|
if(submodel == nullptr)
|
|
error_display(1, "Could not create moveable! Moveable Axis Rotation has no target submodel!");
|
|
|
|
return std::make_shared<ModelAnimationMoveableAxisRotation>(std::move(submodel), velocity, acceleration, axis);
|
|
}
|
|
|
|
|
|
ModelAnimationMoveableIK::ModelAnimationMoveableIK(std::vector<moveable_chainlink> chain, float time) :
|
|
m_time(time), m_chain(std::move(chain)) { }
|
|
|
|
void ModelAnimationMoveableIK::update(polymodel_instance* pmi, const SCP_vector<std::any>& args) {
|
|
if(args.size() < 3){
|
|
Error(LOCATION,"Tried updating moveable IK with too few (%d of 3) arguments!", (int) args.size());
|
|
return;
|
|
}
|
|
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
try {
|
|
auto x = std::any_cast<int>(args[0]), y = std::any_cast<int>(args[1]), z = std::any_cast<int>(args[2]);
|
|
|
|
std::optional<matrix> orient;
|
|
if(args.size() >= 6 && args[3].type() == typeid(int)) {
|
|
auto p = std::any_cast<int>(args[3]), h = std::any_cast<int>(args[4]), b = std::any_cast<int>(args[5]);
|
|
|
|
matrix rot;
|
|
angles ang{ fl_radians(p), fl_radians(b), fl_radians(h) };
|
|
vm_angles_2_matrix(&rot, &ang);
|
|
orient = rot;
|
|
}
|
|
|
|
auto& sequence = *std::static_pointer_cast<ModelAnimationSegmentSerial>(anim->m_animation);
|
|
auto& setOrientationParallel = *std::static_pointer_cast<ModelAnimationSegmentParallel>(sequence.m_segments[0]);
|
|
auto& ik = *std::static_pointer_cast<ModelAnimationSegmentIK>(sequence.m_segments[1]);
|
|
|
|
ModelAnimationSubmodelBuffer buffer;
|
|
for(const auto& segment : setOrientationParallel.m_segments){
|
|
auto& orientation = *std::static_pointer_cast<ModelAnimationSegmentSetOrientation>(segment);
|
|
buffer[orientation.m_submodel].data.orientation = IDENTITY_MATRIX;
|
|
}
|
|
|
|
//Will now only contain the delta of the IK
|
|
anim->m_animation->calculateAnimation(buffer, anim->getTime(pmi->id), pmi->id);
|
|
|
|
anim->forceRecalculate(pmi);
|
|
|
|
for(const auto& segment : setOrientationParallel.m_segments){
|
|
auto& orientation = *std::static_pointer_cast<ModelAnimationSegmentSetOrientation>(segment);
|
|
orientation.m_targetOrientation = buffer[orientation.m_submodel].data.orientation;
|
|
}
|
|
|
|
ik.m_targetRotation = orient;
|
|
ik.m_targetPosition = vec3d{{{x * 0.01f, y * 0.01f, z * 0.01f}}};
|
|
|
|
anim->start(pmi, ModelAnimationDirection::FWD);
|
|
}
|
|
catch(const std::bad_any_cast& e){
|
|
Error(LOCATION, "Argument error trying to update rotation moveable: %s", e.what());
|
|
}
|
|
}
|
|
|
|
void ModelAnimationMoveableIK::initialize(ModelAnimationSet* parentSet, polymodel_instance* pmi) {
|
|
auto& anim = m_instances[pmi->id].animation;
|
|
|
|
anim = std::make_shared<ModelAnimation>(false, false, true, parentSet);
|
|
|
|
auto sequence = std::make_shared<ModelAnimationSegmentSerial>();
|
|
auto parallelSetOrient = std::make_shared<ModelAnimationSegmentParallel>();
|
|
for(const auto& link : m_chain) {
|
|
auto submodel = parentSet->getSubmodel(link.submodel);
|
|
parallelSetOrient->addSegment(std::make_shared<ModelAnimationSegmentSetOrientation>(submodel, vmd_identity_matrix, ModelAnimationCoordinateRelation::RELATIVE_COORDS));
|
|
}
|
|
sequence->addSegment(parallelSetOrient);
|
|
|
|
auto parallelIK = std::make_shared<ModelAnimationSegmentParallel>();
|
|
vec3d startPos = ZERO_VECTOR;
|
|
|
|
for(size_t i = 1; i < m_chain.size(); ++i) {
|
|
startPos += parentSet->getSubmodel(m_chain[i].submodel)->findSubmodel(pmi).second->offset;
|
|
}
|
|
|
|
auto segment = std::make_shared<ModelAnimationSegmentIK>(startPos, std::nullopt);
|
|
segment->m_segment = parallelIK;
|
|
|
|
for(const auto& link : m_chain) {
|
|
auto submodel = parentSet->getSubmodel(link.submodel);
|
|
auto rotation = std::make_shared<ModelAnimationSegmentRotation>(submodel, std::optional<angles>({0,0,0}), std::nullopt, m_time, link.acceleration, ModelAnimationCoordinateRelation::ABSOLUTE_COORDS);
|
|
parallelIK->addSegment(rotation);
|
|
segment->m_chain.push_back({submodel, link.constraint, std::move(rotation)});
|
|
}
|
|
|
|
sequence->addSegment(segment);
|
|
|
|
anim->setAnimation(sequence);
|
|
|
|
anim->start(pmi,ModelAnimationDirection::FWD);
|
|
}
|
|
|
|
std::shared_ptr<ModelAnimationMoveable> ModelAnimationMoveableIK::parser() {
|
|
required_string("+Time:");
|
|
float time;
|
|
stuff_float(&time);
|
|
|
|
std::vector<moveable_chainlink> chain;
|
|
|
|
while (optional_string("$Chain Link:")) {
|
|
auto submodel = ModelAnimationParseHelper::parseSubmodel();
|
|
|
|
std::optional<angles> acceleration;
|
|
if (optional_string("+Acceleration:")) {
|
|
angles accel;
|
|
stuff_angles_deg_phb(&accel);
|
|
acceleration = accel;
|
|
}
|
|
|
|
std::shared_ptr<ik_constraint> constraint;
|
|
if (optional_string("+Constraint:")) {
|
|
int type = required_string_one_of(2, "Window", "Hinge");
|
|
switch (type) {
|
|
case 0: { //Window
|
|
angles window;
|
|
required_string("Window");
|
|
required_string("+Window Size:");
|
|
stuff_angles_deg_phb(&window);
|
|
constraint = std::make_shared<ik_constraint_window>(window);
|
|
break;
|
|
}
|
|
case 1: { //Hinge
|
|
vec3d axis;
|
|
required_string("Hinge");
|
|
required_string("+Axis:");
|
|
stuff_vec3d(&axis);
|
|
vm_vec_normalize(&axis);
|
|
constraint = std::make_shared<ik_constraint_hinge>(axis);
|
|
break;
|
|
}
|
|
default:
|
|
UNREACHABLE("IK constraint of unknown type specified!");
|
|
break;
|
|
}
|
|
} else
|
|
constraint = std::make_shared<ik_constraint>();
|
|
|
|
chain.push_back({std::move(submodel), std::move(constraint), acceleration});
|
|
}
|
|
|
|
return std::make_shared<ModelAnimationMoveableIK>(std::move(chain), time);
|
|
}
|
|
}
|