diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 3dbe5b40af..ae0d8a489d 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -767,7 +767,7 @@ namespace MWRender Misc::StringUtils::replaceLast(yamlpath, ".dae", ".yaml"); // globalBlendConfigPath is only used with actors! Objects have no default blending. - const VFS::Path::NormalizedView globalBlendConfigPath("animations/animation-config.yaml"); + constexpr VFS::Path::NormalizedView globalBlendConfigPath("animations/animation-config.yaml"); const VFS::Path::NormalizedView blendConfigPath(yamlpath); osg::ref_ptr blendRules; diff --git a/apps/openmw/mwrender/animblendcontroller.cpp b/apps/openmw/mwrender/animblendcontroller.cpp index 79f7c23069..2aace7a36d 100644 --- a/apps/openmw/mwrender/animblendcontroller.cpp +++ b/apps/openmw/mwrender/animblendcontroller.cpp @@ -10,84 +10,127 @@ namespace MWRender { - /// Animation Easing/Blending functions - namespace Easings + namespace { - float linear(float x) - { - return x; - } - float sineOut(float x) - { - return sin((x * 3.14) / 2); - } - float sineIn(float x) - { - return 1 - cos((x * 3.14) / 2); - } - float sineInOut(float x) - { - return -(cos(3.14 * x) - 1) / 2; - } - float cubicOut(float t) - { - return 1 - powf(1 - t, 3); - } - float cubicIn(float x) + // Animation Easing/Blending functions + namespace Easings { - return powf(x, 3); - } - float cubicInOut(float x) - { - return x < 0.5 ? 4 * x * x * x : 1 - powf(-2 * x + 2, 3) / 2; - } - float quartOut(float t) - { - return 1 - powf(1 - t, 4); - } - float quartIn(float t) - { - return powf(t, 4); - } - float quartInOut(float x) - { - return x < 0.5 ? 8 * x * x * x * x : 1 - powf(-2 * x + 2, 4) / 2; - } - float springOutGeneric(float x, float lambda, float w) - { - // Higher lambda = lower swing amplitude. 1 = 150% swing amplitude. - // W corresponds to the amount of overswings, more = more. 4.71 = 1 overswing, 7.82 = 2 - return 1 - expf(-lambda * x) * cos(w * x); - } - float springOutWeak(float x) - { - return springOutGeneric(x, 4, 4.71); - } - float springOutMed(float x) - { - return springOutGeneric(x, 3, 4.71); - } - float springOutStrong(float x) - { - return springOutGeneric(x, 2, 4.71); - } - float springOutTooMuch(float x) - { - return springOutGeneric(x, 1, 4.71); + float linear(float x) + { + return x; + } + + float sineOut(float x) + { + return sin((x * osg::PIf) / 2); + } + + float sineIn(float x) + { + return 1 - cos((x * osg::PIf) / 2); + } + + float sineInOut(float x) + { + return -(cos(osg::PIf * x) - 1) / 2; + } + + float cubicOut(float t) + { + float t1 = 1 - t; + return 1 - (t1 * t1 * t1); // (1-t)^3 + } + + float cubicIn(float x) + { + return x * x * x; // x^3 + } + + float cubicInOut(float x) + { + if (x < 0.5) + { + return 4 * x * x * x; // 4x^3 + } + else + { + float x2 = -2 * x + 2; + return 1 - (x2 * x2 * x2) / 2; // (1 - (-2x + 2)^3)/2 + } + } + + float quartOut(float t) + { + float t1 = 1 - t; + return 1 - (t1 * t1 * t1 * t1); // (1-t)^4 + } + + float quartIn(float t) + { + return t * t * t * t; // t^4 + } + + float quartInOut(float x) + { + if (x < 0.5) + { + return 8 * x * x * x * x; // 8x^4 + } + else + { + float x2 = -2 * x + 2; + return 1 - (x2 * x2 * x2 * x2) / 2; // 1 - ((-2x + 2)^4)/2 + } + } + + float springOutGeneric(float x, float lambda, float w) + { + // Higher lambda = lower swing amplitude. 1 = 150% swing amplitude. + // W corresponds to the amount of overswings, more = more. 4.71 = 1 overswing, 7.82 = 2 + return 1 - expf(-lambda * x) * cos(w * x); + } + + float springOutWeak(float x) + { + return springOutGeneric(x, 4, 4.71); + } + + float springOutMed(float x) + { + return springOutGeneric(x, 3, 4.71); + } + + float springOutStrong(float x) + { + return springOutGeneric(x, 2, 4.71); + } + + float springOutTooMuch(float x) + { + return springOutGeneric(x, 1, 4.71); + } + + const std::unordered_map easingsMap = { + { "linear", Easings::linear }, + { "sineOut", Easings::sineOut }, + { "sineIn", Easings::sineIn }, + { "sineInOut", Easings::sineInOut }, + { "cubicOut", Easings::cubicOut }, + { "cubicIn", Easings::cubicIn }, + { "cubicInOut", Easings::cubicInOut }, + { "quartOut", Easings::quartOut }, + { "quartIn", Easings::quartIn }, + { "quartInOut", Easings::quartInOut }, + { "springOutWeak", Easings::springOutWeak }, + { "springOutMed", Easings::springOutMed }, + { "springOutStrong", Easings::springOutStrong }, + { "springOutTooMuch", Easings::springOutTooMuch }, + }; } - std::unordered_map easingsMap = { { "linear", Easings::linear }, - { "sineOut", Easings::sineOut }, { "sineIn", Easings::sineIn }, { "sineInOut", Easings::sineInOut }, - { "cubicOut", Easings::cubicOut }, { "cubicIn", Easings::cubicIn }, { "cubicInOut", Easings::cubicInOut }, - { "quartOut", Easings::quartOut }, { "quartIn", Easings::quartIn }, { "quartInOut", Easings::quartInOut }, - { "springOutWeak", Easings::springOutWeak }, { "springOutMed", Easings::springOutMed }, - { "springOutStrong", Easings::springOutStrong }, { "springOutTooMuch", Easings::springOutTooMuch } }; - } - namespace - { - osg::Vec3f vec3fLerp(float t, const osg::Vec3f& A, const osg::Vec3f& B) + osg::Vec3f vec3fLerp(float t, const osg::Vec3f& start, const osg::Vec3f& end) { - return A + (B - A) * t; + return start + (end - start) * t; } } @@ -129,10 +172,10 @@ namespace MWRender if (blendRule) { - if (Easings::easingsMap.contains(blendRule->mEasing)) + if (const auto it = Easings::easingsMap.find(blendRule->mEasing); it != Easings::easingsMap.end()) { + mEasingFn = it->second; mBlendDuration = blendRule->mDuration; - mEasingFn = Easings::easingsMap[blendRule->mEasing]; } else { diff --git a/apps/openmw/mwrender/animblendcontroller.hpp b/apps/openmw/mwrender/animblendcontroller.hpp index 38d83af7cd..8f8ac03ae0 100644 --- a/apps/openmw/mwrender/animblendcontroller.hpp +++ b/apps/openmw/mwrender/animblendcontroller.hpp @@ -16,10 +16,7 @@ namespace MWRender { - namespace Easings - { - typedef float (*EasingFn)(float); - } + typedef float (*EasingFn)(float); struct AnimBlendStateData { @@ -41,7 +38,7 @@ namespace MWRender bool getBlendTrigger() const { return mBlendTrigger; } protected: - Easings::EasingFn mEasingFn; + EasingFn mEasingFn; float mBlendDuration = 0.0f; float mBlendStartTime = 0.0f; float mTimeFactor = 0.0f; diff --git a/components/sceneutil/serialize.cpp b/components/sceneutil/serialize.cpp index 480d1abf2f..81053aa476 100644 --- a/components/sceneutil/serialize.cpp +++ b/components/sceneutil/serialize.cpp @@ -187,20 +187,48 @@ namespace SceneUtil mgr->addWrapper(new GeometrySerializer); // ignore the below for now to avoid warning spam - const char* ignore[] = { "Debug::DebugDrawer", "MWRender::NifAnimBlendController", - "MWRender::BoneAnimBlendController", "MWRender::BoneAnimBlendControllerWrapper", "MWRender::PtrHolder", - "Resource::TemplateRef", "Resource::TemplateMultiRef", "SceneUtil::CompositeStateSetUpdater", - "SceneUtil::UBOManager", "SceneUtil::LightListCallback", "SceneUtil::LightManagerUpdateCallback", - "SceneUtil::FFPLightStateAttribute", "SceneUtil::UpdateRigBounds", "SceneUtil::UpdateRigGeometry", - "SceneUtil::LightSource", "SceneUtil::DisableLight", "SceneUtil::MWShadowTechnique", - "SceneUtil::TextKeyMapHolder", "Shader::AddedState", "Shader::RemovedAlphaFunc", - "NifOsg::FlipController", "NifOsg::KeyframeController", "NifOsg::Emitter", - "NifOsg::ParticleColorAffector", "NifOsg::ParticleSystem", "NifOsg::GravityAffector", - "NifOsg::ParticleBomb", "NifOsg::GrowFadeAffector", "NifOsg::InverseWorldMatrix", - "NifOsg::StaticBoundingBoxCallback", "NifOsg::GeomMorpherController", "NifOsg::UpdateMorphGeometry", - "NifOsg::UVController", "NifOsg::VisController", "osgMyGUI::Drawable", "osg::DrawCallback", - "osg::UniformBufferObject", "osgOQ::ClearQueriesCallback", "osgOQ::RetrieveQueriesCallback", - "osg::DummyObject" }; + const char* ignore[] = { + "Debug::DebugDrawer", + "MWRender::NifAnimBlendController", + "MWRender::BoneAnimBlendController", + "MWRender::BoneAnimBlendControllerWrapper", + "MWRender::PtrHolder", + "Resource::TemplateRef", + "Resource::TemplateMultiRef", + "SceneUtil::CompositeStateSetUpdater", + "SceneUtil::UBOManager", + "SceneUtil::LightListCallback", + "SceneUtil::LightManagerUpdateCallback", + "SceneUtil::FFPLightStateAttribute", + "SceneUtil::UpdateRigBounds", + "SceneUtil::UpdateRigGeometry", + "SceneUtil::LightSource", + "SceneUtil::DisableLight", + "SceneUtil::MWShadowTechnique", + "SceneUtil::TextKeyMapHolder", + "Shader::AddedState", + "Shader::RemovedAlphaFunc", + "NifOsg::FlipController", + "NifOsg::KeyframeController", + "NifOsg::Emitter", + "NifOsg::ParticleColorAffector", + "NifOsg::ParticleSystem", + "NifOsg::GravityAffector", + "NifOsg::ParticleBomb", + "NifOsg::GrowFadeAffector", + "NifOsg::InverseWorldMatrix", + "NifOsg::StaticBoundingBoxCallback", + "NifOsg::GeomMorpherController", + "NifOsg::UpdateMorphGeometry", + "NifOsg::UVController", + "NifOsg::VisController", + "osgMyGUI::Drawable", + "osg::DrawCallback", + "osg::UniformBufferObject", + "osgOQ::ClearQueriesCallback", + "osgOQ::RetrieveQueriesCallback", + "osg::DummyObject", + }; for (size_t i = 0; i < sizeof(ignore) / sizeof(ignore[0]); ++i) { mgr->addWrapper(makeDummySerializer(ignore[i]));