238{
239 if (AnimationSequence == nullptr)
240 {
241 UE_LOG(LogAnimation,
Error, TEXT(
"CurveExtractor failed. Reason: Invalid Animation"));
242 return;
243 }
244
245 USkeleton* Skeleton = AnimationSequence->GetSkeleton();
246 if (Skeleton == nullptr)
247 {
248 UE_LOG(LogAnimation,
Error,
249 TEXT("CurveExtractor failed. Reason: Animation with invalid Skeleton. Animation: %s"),
250 *GetNameSafe(AnimationSequence));
251 return;
252 }
253
254 const int32 BoneIndex = Skeleton->GetReferenceSkeleton().FindBoneIndex(
BoneName);
255 if (BoneIndex == INDEX_NONE)
256 {
257 UE_LOG(LogAnimation,
Error,
258 TEXT("CurveExtractor failed. Reason: Invalid Bone Index. BoneName: %s Animation: %s Skeleton: %s"),
259 *
BoneName.ToString(), *GetNameSafe(AnimationSequence), *GetNameSafe(Skeleton));
260 return;
261 }
262
263 FMemMark Mark(FMemStack::Get());
264
265 TArray<FBoneIndexType> RequiredBones;
266 RequiredBones.Add(BoneIndex);
267 Skeleton->GetReferenceSkeleton().EnsureParentsExistAndSort(RequiredBones);
268
269 FBoneContainer BoneContainer(RequiredBones, false, *Skeleton);
270 const FCompactPoseBoneIndex CompactPoseBoneIndex = BoneContainer.
271 MakeCompactPoseIndex(FMeshPoseBoneIndex(BoneIndex));
272
273 const float AnimLength = AnimationSequence->GetPlayLength();
274 const float SampleInterval = 1.f /
SampleRate;
275
276 float Time = 0.f;
277 int32 SampleIndex = 0;
278
279 FTransform RefPose =
ExtractPose(AnimationSequence, BoneContainer, CompactPoseBoneIndex, 0.f);
280
281 TArray<FTransform> BonePoses;
282
283 FVector MaxLoc = FVector::ZeroVector;
284 FRotator MaxRot = FRotator::ZeroRotator;
285
286 auto PluginSettings = GetMutableDefault<UPluginSettings>();
287
288 if (!PluginSettings)
289 {
290 UE_LOG(LogTemp,
Error, TEXT(
"Plugin Settings Are NULL"))
291 return;
292 }
293
294 const FString PackagePath = PluginSettings->CurvesSavePath +
WeaponName + FString("_Curves/");
295
296 UPackage* PackageLoc = CreatePackage(*(PackagePath +
AnimName.ToString() + FString("Loc")));
297 PackageLoc->FullyLoad();
298
299 UPackage* PackageRot = CreatePackage(*(PackagePath +
AnimName.ToString() + FString("Rot")));
300 PackageRot->FullyLoad();
301
302 UCurveVector* TranslationCurve = NewObject<UCurveVector>(PackageLoc, *(
AnimName.ToString() + FString("Loc")),
303 RF_Public | RF_Standalone);
304 UCurveVector* RotationCurve = NewObject<UCurveVector>(PackageRot, *(
AnimName.ToString() + FString("Rot")),
305 RF_Public | RF_Standalone);
306
307
308 while (Time < AnimLength)
309 {
310 Time = FMath::Clamp(SampleIndex * SampleInterval, 0.f, AnimLength);
311 SampleIndex++;
312
313 FTransform CurrentPose =
ExtractPose(AnimationSequence, BoneContainer, CompactPoseBoneIndex, Time);
314 FTransform DeltaPose = CurrentPose.Inverse() * RefPose;
315 DeltaPose.NormalizeRotation();
316
318 {
319 if (FMath::Abs(DeltaPose.GetLocation().X) > FMath::Abs(MaxLoc.X))
320 {
321 MaxLoc.X = FMath::Abs(DeltaPose.GetLocation().X);
322 }
323
324 if (FMath::Abs(DeltaPose.GetLocation().Y) > FMath::Abs(MaxLoc.Y))
325 {
326 MaxLoc.Y = FMath::Abs(DeltaPose.GetLocation().Y);
327 }
328
329 if (FMath::Abs(DeltaPose.GetLocation().Z) > FMath::Abs(MaxLoc.Z))
330 {
331 MaxLoc.Z = FMath::Abs(DeltaPose.GetLocation().Z);
332 }
333
334 if (FMath::Abs(DeltaPose.Rotator().Pitch) > FMath::Abs(MaxRot.Pitch))
335 {
336 MaxRot.Pitch = FMath::Abs(DeltaPose.Rotator().Pitch);
337 }
338
339 if (FMath::Abs(DeltaPose.Rotator().Yaw) > FMath::Abs(MaxRot.Yaw))
340 {
341 MaxRot.Yaw = FMath::Abs(DeltaPose.Rotator().Yaw);
342 }
343
344 if (FMath::Abs(DeltaPose.Rotator().Roll) > FMath::Abs(MaxRot.Roll))
345 {
346 MaxRot.Roll = FMath::Abs(DeltaPose.Rotator().Roll);
347 }
348
349 BonePoses.Add(DeltaPose);
350
351 TranslationCurve->FloatCurves[0].UpdateOrAddKey(Time, 0.f, true);
352 TranslationCurve->FloatCurves[1].UpdateOrAddKey(Time, 0.f, true);
353 TranslationCurve->FloatCurves[2].UpdateOrAddKey(Time, 0.f, true);
354
355 RotationCurve->FloatCurves[0].UpdateOrAddKey(Time, 0.f, true);
356 RotationCurve->FloatCurves[1].UpdateOrAddKey(Time, 0.f, true);
357 RotationCurve->FloatCurves[2].UpdateOrAddKey(Time, 0.f, true);
358
359 continue;
360 }
361
362 TranslationCurve->FloatCurves[0].UpdateOrAddKey(Time, DeltaPose.GetLocation().X, true);
363 TranslationCurve->FloatCurves[1].UpdateOrAddKey(Time, DeltaPose.GetLocation().Y, true);
364 TranslationCurve->FloatCurves[2].UpdateOrAddKey(Time, DeltaPose.GetLocation().Z, true);
365
366 RotationCurve->FloatCurves[0].UpdateOrAddKey(Time, DeltaPose.Rotator().Roll, true);
367 RotationCurve->FloatCurves[1].UpdateOrAddKey(Time, DeltaPose.Rotator().Pitch, true);
368 RotationCurve->FloatCurves[2].UpdateOrAddKey(Time, DeltaPose.Rotator().Yaw, true);
369 }
370
372 {
373
374 for (int i = 0; i < BonePoses.Num(); i++)
375 {
376 FVector NormalizedVector;
377 NormalizedVector.X =
NormalizeValue(BonePoses[i].GetLocation().
X, MaxLoc.X);
378 NormalizedVector.Y =
NormalizeValue(BonePoses[i].GetLocation().
Y, MaxLoc.Y);
379 NormalizedVector.Z =
NormalizeValue(BonePoses[i].GetLocation().
Z, MaxLoc.Z);
380
381 FRotator NormalizedRotator;
382 NormalizedRotator.Pitch =
NormalizeValue(BonePoses[i].Rotator().Pitch, MaxRot.Pitch);
383 NormalizedRotator.Yaw =
NormalizeValue(BonePoses[i].Rotator().Yaw, MaxRot.Yaw);
385
386 BonePoses[i] = FTransform(NormalizedRotator, NormalizedVector);
387 }
388
389 for (int i = 0; i < TranslationCurve->FloatCurves->GetNumKeys(); i++)
390 {
391 TranslationCurve->FloatCurves[0].Keys[i].Value = BonePoses[i].GetLocation().X;
392 TranslationCurve->FloatCurves[1].Keys[i].Value = BonePoses[i].GetLocation().Y;
393 TranslationCurve->FloatCurves[2].Keys[i].Value = BonePoses[i].GetLocation().Z;
394
395 RotationCurve->FloatCurves[0].Keys[i].Value = BonePoses[i].Rotator().Roll;
396 RotationCurve->FloatCurves[1].Keys[i].Value = BonePoses[i].Rotator().Pitch;
397 RotationCurve->FloatCurves[2].Keys[i].Value = BonePoses[i].Rotator().Yaw;
398 }
399 }
400
401 SaveCurve(PackageLoc, TranslationCurve, PackagePath +
AnimName.ToString() + FString(
"Loc"));
402 SaveCurve(PackageRot, RotationCurve, PackagePath +
AnimName.ToString() + FString(
"Rot"));
403}