【发布时间】:2021-02-12 03:03:04
【问题描述】:
我正在尝试将一些 Swift 示例(例如 https://github.com/iamfine/ARSkeleton)翻译成 C#,以展示如何使用 ARKit Body Tracking。
但我似乎不太能够将关节节点正确定位在相应的关节上。它们跟随我的身体动作,但节点的位置似乎不正确。
熟悉 ARKit Body Tracking 的人能看出我做错了什么吗?
谢谢
using ARKit;
using Foundation;
using OpenTK;
using SceneKit;
using System;
using System.Collections.Generic;
using UIKit;
namespace XamarinArkitSample
{
public partial class BodyDetectionViewController : UIViewController
{
private readonly ARSCNView sceneView;
public BodyDetectionViewController()
{
this.sceneView = new ARSCNView
{
AutoenablesDefaultLighting = true,
Delegate = new SceneViewDelegate()
};
this.View.AddSubview(this.sceneView);
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.sceneView.Frame = this.View.Frame;
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
var bodyTrackingConfiguration = new ARBodyTrackingConfiguration()
{
WorldAlignment = ARWorldAlignment.Gravity
};
this.sceneView.Session.Run(bodyTrackingConfiguration,
ARSessionRunOptions.ResetTracking | ARSessionRunOptions.RemoveExistingAnchors);
}
public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
this.sceneView.Session.Pause();
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
public class SceneViewDelegate : ARSCNViewDelegate
{
Dictionary<string, JointNode> joints = new Dictionary<string, JointNode>();
float jointRadius = 0.02f;
UIColor jointColour = UIColor.Green;
public override void DidAddNode(ISCNSceneRenderer renderer, SCNNode node, ARAnchor anchor)
{
if (anchor is ARBodyAnchor bodyAnchor)
{
foreach (var jointName in ARSkeletonDefinition.DefaultBody3DSkeletonDefinition.JointNames)
{
var jointNode = MakeJoint(jointRadius, jointColour);
try
{
var jointPosition = GetJointPosition(bodyAnchor, jointName);
jointNode.Position = jointPosition;
//System.Diagnostics.Debug.WriteLine($"Adding {jointName} node to position {jointPosition.X},{jointPosition.Y},{jointPosition.Z}");
if (!joints.ContainsKey(jointName))
{
node.AddChildNode(jointNode);
joints.Add(jointName, jointNode);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"{ex.Message}");
}
}
}
}
public override void DidUpdateNode(ISCNSceneRenderer renderer, SCNNode node, ARAnchor anchor)
{
if (anchor is ARBodyAnchor bodyAnchor)
{
foreach (var jointName in ARSkeletonDefinition.DefaultBody3DSkeletonDefinition.JointNames)
{
try
{
var jointPosition = GetJointPosition(bodyAnchor, jointName);
if (joints.ContainsKey(jointName))
{
joints[jointName].Update(jointPosition);
//System.Diagnostics.Debug.WriteLine($"Updating {jointName} node to position {jointPosition.X},{jointPosition.Y},{jointPosition.Z}");
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"{ex.Message}");
}
}
}
}
private SCNVector3 GetJointPosition(ARBodyAnchor bodyAnchor, string jointName)
{
// https://github.com/iamfine/ARSkeleton
NMatrix4 jointTransform = bodyAnchor.Skeleton.GetModelTransform((NSString)jointName);
// Approach 1
SCNMatrix4 matrix = jointTransform.ToSCNMatrix4();
SCNMatrix4 bodyAnchorTransform = bodyAnchor.Transform.ToSCNMatrix4();
SCNMatrix4.Mult(ref matrix, ref bodyAnchorTransform, out matrix);
return new SCNVector3(matrix.M41, matrix.M42, matrix.M43);
// Approach 2
/*
var result = bodyAnchor.Transform.Column3 + jointTransform.Column3;
return new SCNVector3(result);
*/
}
private JointNode MakeJoint(float jointRadius, UIColor jointColour)
{
var jointNode = new JointNode();
var material = new SCNMaterial();
material.Diffuse.Contents = jointColour;
var jointGeometry = SCNSphere.Create(jointRadius);
jointGeometry.FirstMaterial = material;
jointNode.Geometry = jointGeometry;
return jointNode;
}
}
public class JointNode : SCNNode
{
public void Update(SCNVector3 position)
{
this.Position = position;
}
}
}
public static class Extensions
{
public static SCNMatrix4 ToSCNMatrix4(this NMatrix4 self)
{
var newMatrix = new SCNMatrix4(
self.M11, self.M21, self.M31, self.M41,
self.M12, self.M22, self.M32, self.M42,
self.M13, self.M23, self.M33, self.M43,
self.M14, self.M24, self.M34, self.M44
);
return newMatrix;
}
}
}
【问题讨论】:
-
也许脱掉你的外套?
-
我试过了,谢谢@RobertHarvey。它没有用。
-
自我注意.. 看看这个,即使它是 Unity.. 关于四元数旋转的一些有趣的东西paste.ubuntu.com/p/nvQ7QyQbhSforum.unity.com/threads/…
-
这也可能暗示另一种方法,专注于局部位置和旋转
-
我会再次重试这个版本的ToSCNMatrix4扩展方法..github.com/ewoody/xamarinAR/blob/…