载入中...
搜索中...
未找到
SmrNeuralProvider.cpp
浏览该文件的文档.
2
5#include "common/Diagnostic.h"
6
7#include <algorithm>
8
9namespace eve::animation {
10
11std::string SmrNeuralProvider::name() const { return loadedPath_.empty() ? "tensor-meshret" : "onnx"; }
12
14 if (!profile) return true;
15 if (!profile->getNeuralRetargetEnabled()) return false;
16 const std::string& backend = profile->getNeuralBackend();
17 if (backend == "onnx") return ensureOnnx(*profile).ok();
18 if (backend == "tensor") return true;
19 if (!profile->getNeuralModelPath().empty()) return ensureOnnx(*profile).ok();
20 return true;
21}
22
23Result<void> SmrNeuralProvider::ensureOnnx(const AnimRetargetProfile& profile) const {
24 const std::string& path = profile.getNeuralModelPath();
25 if (path.empty()) {
27 Diagnostic::error(DiagnosticCode::PreconditionViolation, "SmrNeuralProvider: empty ONNX path"));
28 }
29 if (modelLoaded_ && loadedPath_ == path) return Result<void>::success();
30 auto loaded = onnx_.loadFile(path);
31 if (!loaded.ok()) return loaded;
32 loadedPath_ = path;
33 modelLoaded_ = true;
34 return Result<void>::success();
35}
36
37Result<SmrNeuralResult> SmrNeuralProvider::applyRot6d(const SmrNeuralRequest& request, const SmrFeatureBatch& features,
38 const std::vector<float>& rot6d,
39 const std::string& backend) const {
40 if (!request.targetClip || !request.targetSkeleton) {
42 Diagnostic::error(DiagnosticCode::InvalidArgument, "SmrNeuralProvider: null clip/skeleton"));
43 }
44 if (static_cast<int>(rot6d.size()) < features.frames * features.joints * 6) {
46 Diagnostic::error(DiagnosticCode::InvariantViolation, "SmrNeuralProvider: rot6d size mismatch"));
47 }
48
49 AnimClip& clip = *request.targetClip;
50 const float duration = clip.getDuration();
51 for (int joint = 0; joint < features.joints; ++joint) {
52 clip.clearTrack(joint);
53 for (int frame = 0; frame < features.frames; ++frame) {
54 const float time = duration <= 0.f ? 0.f
55 : duration * static_cast<float>(frame) /
56 static_cast<float>(std::max(features.frames - 1, 1));
57 const float* r6 = rot6d.data() + static_cast<size_t>((frame * features.joints + joint) * 6);
58 float qx = 0.f, qy = 0.f, qz = 0.f, qw = 1.f;
59 rot6dToQuat(r6, qx, qy, qz, qw);
60 clip.addRotationKey(joint, time, qx, qy, qz, qw);
61 }
62 }
63
64 SmrNeuralResult result;
65 result.framesWritten = features.frames;
66 result.backend = backend;
67 result.sensorCount = static_cast<size_t>(features.sensors);
68 result.pairCount = static_cast<size_t>(features.pairs);
69 return Result<SmrNeuralResult>::success(std::move(result));
70}
71
73 if (!request.sourceClip || !request.targetClip || !request.sourceSkeleton || !request.targetSkeleton ||
74 !request.profile) {
76 Diagnostic::error(DiagnosticCode::InvalidArgument, "SmrNeuralProvider.retarget: null argument"));
77 }
78
79 SmrFeatureBatch features = buildSmrFeatures(*request.sourceClip, request.sourceSkeleton, request.targetSkeleton,
80 request.sourceSkin, request.targetSkin, 2, 4);
81
82 const std::string& backendHint = request.profile->getNeuralBackend();
83 const bool preferOnnx =
84 backendHint == "onnx" || (backendHint != "tensor" && !request.profile->getNeuralModelPath().empty());
85 if (preferOnnx) {
86 auto ready = ensureOnnx(*request.profile);
87 if (ready.ok()) {
88 auto ran = onnx_.run(features);
89 if (ran.ok()) return applyRot6d(request, features, ran.value(), "onnx");
90 if (backendHint == "onnx") return Result<SmrNeuralResult>::failure(ran.status());
91 } else if (backendHint == "onnx") {
92 return Result<SmrNeuralResult>::failure(ready.status());
93 }
94 }
95
96 auto ran = net_.forward(features);
97 if (!ran.ok()) return Result<SmrNeuralResult>::failure(ran.status());
98 return applyRot6d(request, features, ran.value(), "tensor-meshret");
99}
100
101} // namespace eve::animation
float duration
Stable, structured diagnostics shared by engine modules.
const GltfImportRequest & request
glm::vec4 clip
std::string path
Definition PlayHost.cpp:110
float qy
float qx
float qw
float qz
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
bool ok() const noexcept
Whether this result represents a non-failure outcome.
Definition Result.h:480
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Settings and diagnostics for offline skeletal animation retargeting.
Definition AnimClip.h:27
const std::string & getNeuralBackend() const
Return the neural backend hint.
Definition AnimClip.h:102
const std::string & getNeuralModelPath() const
Return the configured neural model path (may be empty).
Definition AnimClip.h:88
bool getNeuralRetargetEnabled() const
Return whether neural retarget is preferred when a provider is available.
Definition AnimClip.h:95
Result< std::vector< float > > forward(const SmrFeatureBatch &features) const
Owning target rot6d [T*J*6], or structured failure.
std::string name() const override
Name.
Result< SmrNeuralResult > retarget(const SmrNeuralRequest &request) override
Run inference and rewrite request.targetClip local rotations. @lifetime See SmrNeuralRequest; pointer...
bool isReady(const AnimRetargetProfile *profile) const override
True when ONNX is loadable for the profile path, or builtin MeshRet is usable.
Result< void > loadFile(const std::string &path)
Loads file.
Result< std::vector< float > > run(const SmrFeatureBatch &features) const
Run.
SmrFeatureBatch buildSmrFeatures(const AnimClip &sourceClip, const AnimSkeleton *sourceSkeleton, const AnimSkeleton *targetSkeleton, const AnimSkin *, const AnimSkin *, int ringsPerBone, int pointsPerRing)
Build dense SCS + DMI tensors from skeletons/clip (no tensor headers).
void rot6dToQuat(const float in[6], float &qx, float &qy, float &qz, float &qw)
Convert rotation-6D back to a unit quaternion.
Packed MeshRet-style features for one retarget inference window.
Definition SmrFeatures.h:15
Inputs for neural MeshRet-style skinned motion retarget.