diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index 842621e1d..bcbce5986 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -147,6 +147,24 @@ void AnimatedModel::GetNodeTransformation(const StringView& nodeName, Matrix& no GetNodeTransformation(SkinnedModel ? SkinnedModel->FindNode(nodeName) : -1, nodeTransformation, worldSpace); } +int32 AnimatedModel::FindClosestNode(const Vector3& location, bool worldSpace) const +{ + const Vector3 pos = worldSpace ? _transform.WorldToLocal(location) : location; + int32 result = -1; + float closest = MAX_float; + for (int32 nodeIndex = 0; nodeIndex < GraphInstance.NodesPose.Count(); nodeIndex++) + { + const Vector3 node = GraphInstance.NodesPose[nodeIndex].GetTranslation(); + const float dst = Vector3::DistanceSquared(node, pos); + if (dst < closest) + { + closest = dst; + result = nodeIndex; + } + } + return result; +} + #define CHECK_ANIM_GRAPH_PARAM_ACCESS() \ if (!AnimationGraph) \ { \ @@ -234,6 +252,8 @@ void AnimatedModel::SetParameterValue(const Guid& id, const Variant& value) LOG(Warning, "Failed to set animated model '{0}' missing parameter '{1}'", ToString(), id.ToString()); } +#undef CHECK_ANIM_GRAPH_PARAM_ACCESS + float AnimatedModel::GetBlendShapeWeight(const StringView& name) { for (auto& e : _blendShapes.Weights) diff --git a/Source/Engine/Level/Actors/AnimatedModel.h b/Source/Engine/Level/Actors/AnimatedModel.h index bbced6878..748e58fbe 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.h +++ b/Source/Engine/Level/Actors/AnimatedModel.h @@ -208,6 +208,14 @@ public: /// True if convert matrices into world-space, otherwise returned values will be in local-space of the actor. API_FUNCTION() void GetNodeTransformation(const StringView& nodeName, API_PARAM(Out) Matrix& nodeTransformation, bool worldSpace = false) const; + /// + /// Finds the closest node to a given location. + /// + /// The text location (in local-space of the actor or world-space depending on ). + /// True if convert input location is in world-space, otherwise it's in local-space of the actor. + /// The zero-based index of the found node. Returns -1 if skeleton is missing. + API_FUNCTION() int32 FindClosestNode(const Vector3& location, bool worldSpace = false) const; + public: ///