Xamarin.Android 与基于 Android 设备方向的 UrhoSharp 相机节点旋转
Xamarin.Android vs. UrhoSharp camera node rotation based on Android device orientation
在我的 Xamarin.Android 应用程序中,我有从设备的 地磁旋转矢量 获得的 X、Y、Z 轴方向数据复合传感器并使用 CameraNode 的 SensorManager.GetOrientation( ) method. I want to apply this orientation data in UrhoSharp's scene on the Rotation 属性 进行处理。
换句话说,我想使用设备 "orientation" 传感器来控制场景的相机。
到目前为止我在 SensorChanged 事件处理程序中做了什么:
// app -> an instance of Urho.SimpleApplication
public void OnSensorChanged(SensorEvent e) {
if (e.Sensor.Type == SensorType.GeomagneticRotationVector) {
var rm = new float[9];
SensorManager.GetRotationMatrixFromVector(rm, e.Values.ToArray());
var ov = new float[3];
SensorManager.GetOrientation(rm, ov);
app.Pitch = (Urho.MathHelper.RadiansToDegrees(ov[0]) + 360) % 360; // map [-Pi...+Pi] to [0...360]
app.Yaw = (Urho.MathHelper.RadiansToDegrees(ov[1]) + 360) % 360; // map [-Pi/2...+Pi/2] to [0...360]
app.CameraNode.Rotation = new Urho.Quaternion(app.Pitch, app.Yaw, 0);
}
}
但不幸的是,它并没有像预期的那样工作,而且相机总是看向错误的方向。有什么想法吗?
OnSensorChanged
应该是这样的:
if (e.Sensor == mRotationSensor)
{
var rm = new float[9];
SensorManager.GetRotationMatrixFromVector(rm, e.Values.ToArray());
var ov = new float[3];
SensorManager.GetOrientation(rm, ov);
app.pitch = (Urho.MathHelper.RadiansToDegrees(ov[1]) + 360) % 360; // map [-Pi...+Pi] to [0...360]
app.yaw = (Urho.MathHelper.RadiansToDegrees(ov[0]) + 360) % 360;
Log.Error("pitch=",app.pitch+"");
Log.Error("yaw=", app.yaw + "");
// map [-Pi/2...+Pi/2] to [0...360]
app.cameraNode.Rotation = new Urho.Quaternion(app.pitch, app.yaw, 0);
}
并且您需要在 OnCreate
方法中为您的 SensorManager
添加这些:
mSensorManager = (SensorManager)GetSystemService(Activity.SensorService);
mRotationSensor = mSensorManager.GetDefaultSensor(SensorType.RotationVector);
mSensorManager.RegisterListener(this, mRotationSensor, SensorDelay.Game);
并添加变量:
private SensorManager mSensorManager;
private Sensor mRotationSensor;
最后别忘了为您实现 ISensorEventListener
接口 Activity。
我在 github
上提供了一个演示
最后我在@joe
的一些研究和帮助下解决了这个问题
这是方法的最终版本:
// [app] is an instance of Urho.SimpleApplication
public void OnSensorChanged(SensorEvent e) {
if (e.Sensor.Type == SensorType.GeomagneticRotationVector) {
var inR = new float[9];
SensorManager.GetRotationMatrixFromVector(inR, e.Values.ToArray());
var outR = new float[9];
// we need to remap cooridante system, since the Y and Z axes will be swapped, when we pick up the device
if (SensorManager.RemapCoordinateSystem(inR, Android.Hardware.Axis.X, Android.Hardware.Axis.Z, outR)) {
var ov = new float[3];
SensorManager.GetOrientation(outR, ov);
try {
app.Pitch = (MathHelper.RadiansToDegrees(ov[1]) + 360) % 360;
app.Yaw = (MathHelper.RadiansToDegrees(ov[0]) + 360) % 360;
app.CameraNode.Rotation = new Quaternion(app.Pitch, app.Yaw, 0);
}
catch (System.Exception ex) {
// while Urho.SimpleApplication is not fully started, the [app] properties are not available
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
}
}
另一种可能的使用四元数的解决方案:
public void OnSensorChanged(SensorEvent e) {
if (e.Sensor.Type == SensorType.GeomagneticRotationVector) {
var qv = new float[4];
SensorManager.GetQuaternionFromVector(qv, e.Values.ToArray());
try {
app.CameraNode.Rotation = new Quaternion(qv[1], -qv[3], qv[2], qv[0]);
app.CameraNode.Pitch(90.0f);
app.CameraNode.Roll(180.0f);
}
catch (System.Exception ex) {
}
}
}
在我的 Xamarin.Android 应用程序中,我有从设备的 地磁旋转矢量 获得的 X、Y、Z 轴方向数据复合传感器并使用 CameraNode 的 SensorManager.GetOrientation( ) method. I want to apply this orientation data in UrhoSharp's scene on the Rotation 属性 进行处理。 换句话说,我想使用设备 "orientation" 传感器来控制场景的相机。
到目前为止我在 SensorChanged 事件处理程序中做了什么:
// app -> an instance of Urho.SimpleApplication
public void OnSensorChanged(SensorEvent e) {
if (e.Sensor.Type == SensorType.GeomagneticRotationVector) {
var rm = new float[9];
SensorManager.GetRotationMatrixFromVector(rm, e.Values.ToArray());
var ov = new float[3];
SensorManager.GetOrientation(rm, ov);
app.Pitch = (Urho.MathHelper.RadiansToDegrees(ov[0]) + 360) % 360; // map [-Pi...+Pi] to [0...360]
app.Yaw = (Urho.MathHelper.RadiansToDegrees(ov[1]) + 360) % 360; // map [-Pi/2...+Pi/2] to [0...360]
app.CameraNode.Rotation = new Urho.Quaternion(app.Pitch, app.Yaw, 0);
}
}
但不幸的是,它并没有像预期的那样工作,而且相机总是看向错误的方向。有什么想法吗?
OnSensorChanged
应该是这样的:
if (e.Sensor == mRotationSensor)
{
var rm = new float[9];
SensorManager.GetRotationMatrixFromVector(rm, e.Values.ToArray());
var ov = new float[3];
SensorManager.GetOrientation(rm, ov);
app.pitch = (Urho.MathHelper.RadiansToDegrees(ov[1]) + 360) % 360; // map [-Pi...+Pi] to [0...360]
app.yaw = (Urho.MathHelper.RadiansToDegrees(ov[0]) + 360) % 360;
Log.Error("pitch=",app.pitch+"");
Log.Error("yaw=", app.yaw + "");
// map [-Pi/2...+Pi/2] to [0...360]
app.cameraNode.Rotation = new Urho.Quaternion(app.pitch, app.yaw, 0);
}
并且您需要在 OnCreate
方法中为您的 SensorManager
添加这些:
mSensorManager = (SensorManager)GetSystemService(Activity.SensorService);
mRotationSensor = mSensorManager.GetDefaultSensor(SensorType.RotationVector);
mSensorManager.RegisterListener(this, mRotationSensor, SensorDelay.Game);
并添加变量:
private SensorManager mSensorManager;
private Sensor mRotationSensor;
最后别忘了为您实现 ISensorEventListener
接口 Activity。
我在 github
上提供了一个演示最后我在@joe
的一些研究和帮助下解决了这个问题这是方法的最终版本:
// [app] is an instance of Urho.SimpleApplication
public void OnSensorChanged(SensorEvent e) {
if (e.Sensor.Type == SensorType.GeomagneticRotationVector) {
var inR = new float[9];
SensorManager.GetRotationMatrixFromVector(inR, e.Values.ToArray());
var outR = new float[9];
// we need to remap cooridante system, since the Y and Z axes will be swapped, when we pick up the device
if (SensorManager.RemapCoordinateSystem(inR, Android.Hardware.Axis.X, Android.Hardware.Axis.Z, outR)) {
var ov = new float[3];
SensorManager.GetOrientation(outR, ov);
try {
app.Pitch = (MathHelper.RadiansToDegrees(ov[1]) + 360) % 360;
app.Yaw = (MathHelper.RadiansToDegrees(ov[0]) + 360) % 360;
app.CameraNode.Rotation = new Quaternion(app.Pitch, app.Yaw, 0);
}
catch (System.Exception ex) {
// while Urho.SimpleApplication is not fully started, the [app] properties are not available
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
}
}
另一种可能的使用四元数的解决方案:
public void OnSensorChanged(SensorEvent e) {
if (e.Sensor.Type == SensorType.GeomagneticRotationVector) {
var qv = new float[4];
SensorManager.GetQuaternionFromVector(qv, e.Values.ToArray());
try {
app.CameraNode.Rotation = new Quaternion(qv[1], -qv[3], qv[2], qv[0]);
app.CameraNode.Pitch(90.0f);
app.CameraNode.Roll(180.0f);
}
catch (System.Exception ex) {
}
}
}