mirror of
https://github.com/oliverbooth/VpSharp
synced 2024-11-22 19:38:47 +00:00
Replace usages of Quaternion with custom Rotation struct
This commit is contained in:
parent
b7e43666b5
commit
342820b444
@ -1,6 +1,5 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using VpSharp.Extensions;
|
|
||||||
using VpSharp.Internal;
|
using VpSharp.Internal;
|
||||||
using VpSharp.Internal.NativeAttributes;
|
using VpSharp.Internal.NativeAttributes;
|
||||||
using X10D.Numerics;
|
using X10D.Numerics;
|
||||||
@ -314,7 +313,7 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
public Task TeleportAsync(VirtualParadiseWorld world, Vector3d position)
|
public Task TeleportAsync(VirtualParadiseWorld world, Vector3d position)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(world);
|
ArgumentNullException.ThrowIfNull(world);
|
||||||
return TeleportAsync(world.Name, position, Quaternion.Identity);
|
return TeleportAsync(world.Name, position, Rotation.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -324,7 +323,7 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
/// <param name="position">The position to which this avatar should be teleported.</param>
|
/// <param name="position">The position to which this avatar should be teleported.</param>
|
||||||
/// <param name="rotation">The rotation to which this avatar should be teleported.</param>
|
/// <param name="rotation">The rotation to which this avatar should be teleported.</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="world" /> is <see langword="null" />.</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="world" /> is <see langword="null" />.</exception>
|
||||||
public Task TeleportAsync(VirtualParadiseWorld world, Vector3d position, Quaternion rotation)
|
public Task TeleportAsync(VirtualParadiseWorld world, Vector3d position, Rotation rotation)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(world);
|
ArgumentNullException.ThrowIfNull(world);
|
||||||
return TeleportAsync(world.Name, position, rotation);
|
return TeleportAsync(world.Name, position, rotation);
|
||||||
@ -337,7 +336,7 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
/// <param name="position">The position to which this avatar should be teleported.</param>
|
/// <param name="position">The position to which this avatar should be teleported.</param>
|
||||||
public Task TeleportAsync(string world, Vector3d position)
|
public Task TeleportAsync(string world, Vector3d position)
|
||||||
{
|
{
|
||||||
return TeleportAsync(world, position, Quaternion.Identity);
|
return TeleportAsync(world, position, Rotation.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -346,7 +345,7 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
/// <param name="world">The name of the world to which this avatar should be teleported.</param>
|
/// <param name="world">The name of the world to which this avatar should be teleported.</param>
|
||||||
/// <param name="position">The position to which this avatar should be teleported.</param>
|
/// <param name="position">The position to which this avatar should be teleported.</param>
|
||||||
/// <param name="rotation">The rotation to which this avatar should be teleported.</param>
|
/// <param name="rotation">The rotation to which this avatar should be teleported.</param>
|
||||||
public async Task TeleportAsync(string world, Vector3d position, Quaternion rotation)
|
public async Task TeleportAsync(string world, Vector3d position, Rotation rotation)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(world);
|
ArgumentNullException.ThrowIfNull(world);
|
||||||
#if NET7_0_OR_GREATER
|
#if NET7_0_OR_GREATER
|
||||||
@ -385,7 +384,7 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
lock (_client.Lock)
|
lock (_client.Lock)
|
||||||
{
|
{
|
||||||
(double x, double y, double z) = position;
|
(double x, double y, double z) = position;
|
||||||
(double pitch, double yaw, double _) = rotation.ToEulerAngles();
|
(double pitch, double yaw, double _) = rotation;
|
||||||
|
|
||||||
_ = vp_double_set(handle, FloatAttribute.MyX, x);
|
_ = vp_double_set(handle, FloatAttribute.MyX, x);
|
||||||
_ = vp_double_set(handle, FloatAttribute.MyY, y);
|
_ = vp_double_set(handle, FloatAttribute.MyY, y);
|
||||||
@ -405,9 +404,9 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
lock (_client.Lock)
|
lock (_client.Lock)
|
||||||
{
|
{
|
||||||
(float x, float y, float z) = (Vector3)position;
|
(float x, float y, float z) = (Vector3)position;
|
||||||
(float pitch, float yaw, float _) = (Vector3)rotation.ToEulerAngles();
|
(double pitch, double yaw, double _) = rotation;
|
||||||
|
|
||||||
var reason = (ReasonCode)vp_teleport_avatar(handle, Session, world, x, y, z, yaw, pitch);
|
var reason = (ReasonCode)vp_teleport_avatar(handle, Session, world, x, y, z, (float)yaw, (float)pitch);
|
||||||
if (reason == ReasonCode.NotInWorld)
|
if (reason == ReasonCode.NotInWorld)
|
||||||
{
|
{
|
||||||
ThrowHelper.ThrowNotInWorldException();
|
ThrowHelper.ThrowNotInWorldException();
|
||||||
@ -433,7 +432,7 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="position">The position to which this avatar should be teleported.</param>
|
/// <param name="position">The position to which this avatar should be teleported.</param>
|
||||||
/// <param name="rotation">The rotation to which this avatar should be teleported</param>
|
/// <param name="rotation">The rotation to which this avatar should be teleported</param>
|
||||||
public Task TeleportAsync(Vector3d position, Quaternion rotation)
|
public Task TeleportAsync(Vector3d position, Rotation rotation)
|
||||||
{
|
{
|
||||||
return TeleportAsync(Location with {Position = position, Rotation = rotation});
|
return TeleportAsync(Location with {Position = position, Rotation = rotation});
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ public abstract class VirtualParadiseObject : IEquatable<VirtualParadiseObject>
|
|||||||
|
|
||||||
Location location = Location;
|
Location location = Location;
|
||||||
Vector3d position = location.Position;
|
Vector3d position = location.Position;
|
||||||
Quaternion rotation = location.Rotation;
|
Rotation rotation = location.Rotation;
|
||||||
|
|
||||||
if (builder.Position.HasValue)
|
if (builder.Position.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
using System.Numerics;
|
using VpSharp.Internal;
|
||||||
using VpSharp.Extensions;
|
|
||||||
using VpSharp.Internal;
|
|
||||||
using X10D.Math;
|
|
||||||
using static VpSharp.Internal.NativeAttributes.DataAttribute;
|
using static VpSharp.Internal.NativeAttributes.DataAttribute;
|
||||||
using static VpSharp.Internal.NativeAttributes.FloatAttribute;
|
using static VpSharp.Internal.NativeAttributes.FloatAttribute;
|
||||||
using static VpSharp.Internal.NativeAttributes.IntegerAttribute;
|
using static VpSharp.Internal.NativeAttributes.IntegerAttribute;
|
||||||
@ -57,7 +54,7 @@ public abstract class VirtualParadiseObjectBuilder
|
|||||||
/// Gets or sets the rotation of the object.
|
/// Gets or sets the rotation of the object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The rotation of the object, or <see langword="default" /> to leave unchanged.</value>
|
/// <value>The rotation of the object, or <see langword="default" /> to leave unchanged.</value>
|
||||||
public Optional<Quaternion> Rotation { get; set; }
|
public Optional<Rotation> Rotation { get; set; }
|
||||||
|
|
||||||
internal Optional<IReadOnlyList<byte>> Data { get; set; }
|
internal Optional<IReadOnlyList<byte>> Data { get; set; }
|
||||||
|
|
||||||
@ -157,27 +154,12 @@ public abstract class VirtualParadiseObjectBuilder
|
|||||||
|
|
||||||
if (!Rotation.HasValue && Mode == ObjectBuilderMode.Create)
|
if (!Rotation.HasValue && Mode == ObjectBuilderMode.Create)
|
||||||
{
|
{
|
||||||
Rotation = Quaternion.Identity;
|
Rotation = VpSharp.Rotation.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Rotation.HasValue)
|
if (Rotation.HasValue)
|
||||||
{
|
{
|
||||||
(double x, double y, double z) = Vector3d.Zero;
|
(double x, double y, double z, double angle) = Rotation.Value;
|
||||||
double angle = double.PositiveInfinity;
|
|
||||||
if (Rotation.Value != Quaternion.Identity)
|
|
||||||
{
|
|
||||||
Rotation.Value.ToAxisAngle(out Vector3d axis, out angle);
|
|
||||||
(x, y, z) = axis;
|
|
||||||
angle = angle.RadiansToDegrees();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (double.IsPositiveInfinity(angle))
|
|
||||||
{
|
|
||||||
x = x.RadiansToDegrees();
|
|
||||||
y = y.RadiansToDegrees();
|
|
||||||
z = z.RadiansToDegrees();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = vp_double_set(handle, ObjectRotationX, x);
|
_ = vp_double_set(handle, ObjectRotationX, x);
|
||||||
_ = vp_double_set(handle, ObjectRotationY, y);
|
_ = vp_double_set(handle, ObjectRotationY, y);
|
||||||
_ = vp_double_set(handle, ObjectRotationZ, z);
|
_ = vp_double_set(handle, ObjectRotationZ, z);
|
||||||
@ -185,16 +167,10 @@ public abstract class VirtualParadiseObjectBuilder
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetObject.Location.Rotation.ToAxisAngle(out Vector3d axis, out double angle);
|
(double x, double y, double z, double angle) = TargetObject.Location.Rotation;
|
||||||
if (Vector3d.IsNan(axis))
|
_ = vp_double_set(handle, ObjectRotationX, x);
|
||||||
{
|
_ = vp_double_set(handle, ObjectRotationY, y);
|
||||||
axis = Vector3d.Zero;
|
_ = vp_double_set(handle, ObjectRotationZ, z);
|
||||||
angle = double.PositiveInfinity;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = vp_double_set(handle, ObjectRotationX, axis.X);
|
|
||||||
_ = vp_double_set(handle, ObjectRotationY, axis.Y);
|
|
||||||
_ = vp_double_set(handle, ObjectRotationZ, axis.Z);
|
|
||||||
_ = vp_double_set(handle, ObjectRotationAngle, angle);
|
_ = vp_double_set(handle, ObjectRotationAngle, angle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using System.Numerics;
|
|
||||||
using VpSharp.Exceptions;
|
using VpSharp.Exceptions;
|
||||||
using VpSharp.Extensions;
|
|
||||||
using VpSharp.Internal;
|
using VpSharp.Internal;
|
||||||
using VpSharp.Internal.NativeAttributes;
|
using VpSharp.Internal.NativeAttributes;
|
||||||
using static VpSharp.Internal.NativeMethods;
|
using static VpSharp.Internal.NativeMethods;
|
||||||
@ -144,7 +142,7 @@ public sealed class VirtualParadiseUser : IEquatable<VirtualParadiseUser>
|
|||||||
|
|
||||||
string world = location.Value.World.Name;
|
string world = location.Value.World.Name;
|
||||||
(double x, double y, double z) = location.Value.Position;
|
(double x, double y, double z) = location.Value.Position;
|
||||||
(double pitch, double yaw, _) = location.Value.Rotation.ToEulerAngles();
|
(double pitch, double yaw, _) = location.Value.Rotation;
|
||||||
|
|
||||||
_ = vp_int_set(_client.NativeInstanceHandle, IntegerAttribute.ReferenceNumber, reference);
|
_ = vp_int_set(_client.NativeInstanceHandle, IntegerAttribute.ReferenceNumber, reference);
|
||||||
_ = vp_invite(_client.NativeInstanceHandle, Id, world, x, y, z, (float)yaw, (float)pitch);
|
_ = vp_invite(_client.NativeInstanceHandle, Id, world, x, y, z, (float)yaw, (float)pitch);
|
||||||
@ -215,7 +213,7 @@ public sealed class VirtualParadiseUser : IEquatable<VirtualParadiseUser>
|
|||||||
}
|
}
|
||||||
|
|
||||||
var position = new Vector3d(x, y, z);
|
var position = new Vector3d(x, y, z);
|
||||||
var rotation = Quaternion.CreateFromYawPitchRoll(yaw, pitch, 0);
|
var rotation = Rotation.CreateFromTiltYawRoll(pitch, yaw, 0);
|
||||||
VirtualParadiseWorld world = (await _client.GetWorldAsync(worldName).ConfigureAwait(false))!;
|
VirtualParadiseWorld world = (await _client.GetWorldAsync(worldName).ConfigureAwait(false))!;
|
||||||
|
|
||||||
location = new Location(world, position, rotation);
|
location = new Location(world, position, rotation);
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace VpSharp.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for <see cref="Quaternion" />.
|
|
||||||
/// </summary>
|
|
||||||
public static class QuaternionExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Converts this quaternion to a <see cref="Vector3d" /> containing an Euler representation of the rotation.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The quaternion to convert.</param>
|
|
||||||
/// <returns>The Euler representation of <paramref name="value" />.</returns>
|
|
||||||
/// <see href="https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/" />
|
|
||||||
public static Vector3d ToEulerAngles(this Quaternion value)
|
|
||||||
{
|
|
||||||
value = Quaternion.Normalize(value);
|
|
||||||
double x = Math.Atan2(2 * (value.X * value.W - value.Y * value.Z), 1 - 2 * (value.X * value.X + value.Z * value.Z));
|
|
||||||
double y = Math.Asin(2 * (value.X * value.Z + value.Y * value.W));
|
|
||||||
double z = Math.Atan2(2 * (value.Z * value.W - value.X * value.Y), 1 - 2 * (value.Y * value.Y + value.Z * value.Z));
|
|
||||||
return new Vector3d(x, y, z) * (180 / Math.PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts this quaternion to an axis/angle pair.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The quaternion to convert.</param>
|
|
||||||
/// <param name="axis">The axis value.</param>
|
|
||||||
/// <param name="angle">The angle value.</param>
|
|
||||||
#pragma warning disable CA1021
|
|
||||||
public static void ToAxisAngle(this Quaternion value, out Vector3d axis, out double angle)
|
|
||||||
#pragma warning restore CA1021
|
|
||||||
{
|
|
||||||
angle = 2 * Math.Acos(value.W);
|
|
||||||
axis = Vector3d.Normalize(new Vector3d(value.X, value.Y, value.Z));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
using VpSharp.Exceptions;
|
using VpSharp.Exceptions;
|
||||||
using VpSharp.Extensions;
|
|
||||||
using VpSharp.Internal;
|
using VpSharp.Internal;
|
||||||
|
|
||||||
namespace VpSharp;
|
namespace VpSharp;
|
||||||
@ -76,7 +75,7 @@ public sealed class JoinRequest : IEquatable<JoinRequest>
|
|||||||
location ??= _client.CurrentAvatar.Location;
|
location ??= _client.CurrentAvatar.Location;
|
||||||
string worldName = location.Value.World.Name;
|
string worldName = location.Value.World.Name;
|
||||||
(double x, double y, double z) = location.Value.Position;
|
(double x, double y, double z) = location.Value.Position;
|
||||||
(double pitch, double yaw, double _) = location.Value.Rotation.ToEulerAngles();
|
(double pitch, double yaw, double _) = location.Value.Rotation;
|
||||||
|
|
||||||
lock (_client.Lock)
|
lock (_client.Lock)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
using System.Numerics;
|
using VpSharp.Entities;
|
||||||
using VpSharp.Entities;
|
|
||||||
using VpSharp.Extensions;
|
|
||||||
using X10D.Math;
|
|
||||||
|
|
||||||
namespace VpSharp;
|
namespace VpSharp;
|
||||||
|
|
||||||
@ -29,7 +26,7 @@ public readonly struct Location : IEquatable<Location>
|
|||||||
{
|
{
|
||||||
World = world ?? throw new ArgumentNullException(nameof(world));
|
World = world ?? throw new ArgumentNullException(nameof(world));
|
||||||
Position = new Vector3d(coordinates.X, coordinates.Y, coordinates.Z);
|
Position = new Vector3d(coordinates.X, coordinates.Y, coordinates.Z);
|
||||||
Rotation = Quaternion.CreateFromYawPitchRoll((float)coordinates.Yaw.DegreesToRadians(), 0, 0);
|
Rotation = Rotation.CreateFromTiltYawRoll(0, coordinates.Yaw, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -39,7 +36,7 @@ public readonly struct Location : IEquatable<Location>
|
|||||||
/// <param name="position">The position.</param>
|
/// <param name="position">The position.</param>
|
||||||
/// <param name="rotation">The rotation.</param>
|
/// <param name="rotation">The rotation.</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="world" /> is <see langword="null" />.</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="world" /> is <see langword="null" />.</exception>
|
||||||
public Location(VirtualParadiseWorld world, Vector3d position = default, Quaternion rotation = default)
|
public Location(VirtualParadiseWorld world, Vector3d position = default, Rotation rotation = default)
|
||||||
{
|
{
|
||||||
World = world ?? throw new ArgumentNullException(nameof(world));
|
World = world ?? throw new ArgumentNullException(nameof(world));
|
||||||
Position = position;
|
Position = position;
|
||||||
@ -64,7 +61,7 @@ public readonly struct Location : IEquatable<Location>
|
|||||||
/// Gets the rotation represented by this location.
|
/// Gets the rotation represented by this location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The rotation.</value>
|
/// <value>The rotation.</value>
|
||||||
public Quaternion Rotation { get; init; }
|
public Rotation Rotation { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the world represented by this location.
|
/// Gets the world represented by this location.
|
||||||
@ -131,8 +128,7 @@ public readonly struct Location : IEquatable<Location>
|
|||||||
public Coordinates ToCoordinates()
|
public Coordinates ToCoordinates()
|
||||||
{
|
{
|
||||||
(double x, double y, double z) = Position;
|
(double x, double y, double z) = Position;
|
||||||
(_, double yaw, _) = Rotation.ToEulerAngles();
|
return new Coordinates(World?.Name, x, y, z, Rotation.Yaw);
|
||||||
return new Coordinates(World?.Name, x, y, z, yaw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
172
VpSharp/src/Rotation.cs
Normal file
172
VpSharp/src/Rotation.cs
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using X10D.Math;
|
||||||
|
using X10D.Numerics;
|
||||||
|
|
||||||
|
namespace VpSharp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a rotation.
|
||||||
|
/// </summary>
|
||||||
|
public readonly struct Rotation : IEquatable<Rotation>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents no rotation.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Rotation None = new(0, 0, 0, double.PositiveInfinity);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Rotation" /> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tilt">The tilt.</param>
|
||||||
|
/// <param name="yaw">The yaw.</param>
|
||||||
|
/// <param name="roll">The roll.</param>
|
||||||
|
/// <param name="angle">The angle.</param>
|
||||||
|
public Rotation(double tilt, double yaw, double roll, double angle)
|
||||||
|
{
|
||||||
|
Angle = angle;
|
||||||
|
Roll = roll;
|
||||||
|
Tilt = tilt;
|
||||||
|
Yaw = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the angle component of this rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The angle component.</value>
|
||||||
|
public double Angle { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the roll component of this rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The roll component.</value>
|
||||||
|
/// <remarks>This value is the rotation on the Z axis.</remarks>
|
||||||
|
public double Roll { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the tilt component of this rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The tilt component.</value>
|
||||||
|
/// <remarks>This value is the rotation on the X axis.</remarks>
|
||||||
|
public double Tilt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the yaw component of this rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The yaw component.</value>
|
||||||
|
/// <remarks>This value is the rotation on the Y axis.</remarks>
|
||||||
|
public double Yaw { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the two given rotations are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The first rotation to compare.</param>
|
||||||
|
/// <param name="right">The second rotation to compare.</param>
|
||||||
|
/// <returns><see langword="true" /> if the two rotations are equal; otherwise, <see langword="false" />.</returns>
|
||||||
|
public static bool operator ==(Rotation left, Rotation right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the two given rotations are not equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The first rotation to compare.</param>
|
||||||
|
/// <param name="right">The second rotation to compare.</param>
|
||||||
|
/// <returns><see langword="true" /> if the two rotations are not equal; otherwise, <see langword="false" />.</returns>
|
||||||
|
public static bool operator !=(Rotation left, Rotation right)
|
||||||
|
{
|
||||||
|
return !left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="Rotation" /> from the specified axis and angle, as represented in degrees.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="axis">The axis value.</param>
|
||||||
|
/// <param name="angle">The angle value.</param>
|
||||||
|
/// <returns>A new instance of <see cref="Rotation" />.</returns>
|
||||||
|
public static Rotation CreateFromAxisAngle(Vector3d axis, double angle)
|
||||||
|
{
|
||||||
|
return new Rotation(axis.X, axis.Y, axis.Z, angle.DegreesToRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="Rotation" /> from the specified quaternion.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quaternion">The quaternion.</param>
|
||||||
|
/// <returns>A new instance of <see cref="Rotation" />.</returns>
|
||||||
|
public static Rotation CreateFromQuaternion(Quaternion quaternion)
|
||||||
|
{
|
||||||
|
(Vector3d axis, double angle) = quaternion.ToAxisAngle();
|
||||||
|
return new Rotation(axis.X, axis.Y, axis.Z, angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="Rotation" /> from the specified Euler rotation vector, as represented in degrees.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vector">The Euler rotation vector.</param>
|
||||||
|
/// <returns>A new instance of <see cref="Rotation" />.</returns>
|
||||||
|
public static Rotation CreateFromTiltYawRoll(Vector3d vector)
|
||||||
|
{
|
||||||
|
return new Rotation(vector.X, vector.Y, vector.Z, double.PositiveInfinity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="Rotation" /> from the specified tilt, yaw, and roll, as represented in degrees.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tilt">The tilt.</param>
|
||||||
|
/// <param name="yaw">The yaw.</param>
|
||||||
|
/// <param name="roll">The roll.</param>
|
||||||
|
/// <returns>A new instance of <see cref="Rotation" />.</returns>
|
||||||
|
public static Rotation CreateFromTiltYawRoll(double tilt, double yaw, double roll)
|
||||||
|
{
|
||||||
|
return new Rotation(tilt, yaw, roll, double.PositiveInfinity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deconstructs this rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tilt">When this method returns, contains the <see cref="Tilt" /> component value.</param>
|
||||||
|
/// <param name="yaw">When this method returns, contains the <see cref="Yaw" /> component value.</param>
|
||||||
|
/// <param name="roll">When this method returns, contains the <see cref="Roll" /> component value.</param>
|
||||||
|
public void Deconstruct(out double tilt, out double yaw, out double roll)
|
||||||
|
{
|
||||||
|
Deconstruct(out tilt, out yaw, out roll, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deconstructs this rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tilt">When this method returns, contains the <see cref="Tilt" /> component value.</param>
|
||||||
|
/// <param name="yaw">When this method returns, contains the <see cref="Yaw" /> component value.</param>
|
||||||
|
/// <param name="roll">When this method returns, contains the <see cref="Roll" /> component value.</param>
|
||||||
|
/// <param name="angle">When this method returns, contains the <see cref="Angle" /> component value.</param>
|
||||||
|
public void Deconstruct(out double tilt, out double yaw, out double roll, out double angle)
|
||||||
|
{
|
||||||
|
tilt = Tilt;
|
||||||
|
yaw = Yaw;
|
||||||
|
roll = Roll;
|
||||||
|
angle = Angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether this rotation and another rotation are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The rotation to compare with this instance.</param>
|
||||||
|
/// <returns><see langword="true" /> if the two rotations are equal; otherwise, <see langword="false" />.</returns>
|
||||||
|
public bool Equals(Rotation other)
|
||||||
|
{
|
||||||
|
return Angle.Equals(other.Angle) && Roll.Equals(other.Roll) && Tilt.Equals(other.Tilt) && Yaw.Equals(other.Yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is Rotation other && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(Angle, Roll, Tilt, Yaw);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Numerics;
|
|
||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
using VpSharp.Internal.NativeAttributes;
|
using VpSharp.Internal.NativeAttributes;
|
||||||
using static VpSharp.Internal.NativeMethods;
|
using static VpSharp.Internal.NativeMethods;
|
||||||
@ -52,7 +51,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
var yaw = (float)vp_double(sender, FloatAttribute.AvatarYaw);
|
var yaw = (float)vp_double(sender, FloatAttribute.AvatarYaw);
|
||||||
|
|
||||||
var position = new Vector3d(x, y, z);
|
var position = new Vector3d(x, y, z);
|
||||||
var rotation = Quaternion.CreateFromYawPitchRoll(yaw, pitch, 0);
|
var rotation = Rotation.CreateFromTiltYawRoll(pitch, yaw, 0);
|
||||||
|
|
||||||
string applicationName = vp_string(sender, StringAttribute.AvatarApplicationName);
|
string applicationName = vp_string(sender, StringAttribute.AvatarApplicationName);
|
||||||
string applicationVersion = vp_string(sender, StringAttribute.AvatarApplicationVersion);
|
string applicationVersion = vp_string(sender, StringAttribute.AvatarApplicationVersion);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Numerics;
|
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using VpSharp.ClientExtensions;
|
using VpSharp.ClientExtensions;
|
||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
@ -103,7 +102,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
int session;
|
int session;
|
||||||
int type;
|
int type;
|
||||||
Vector3d position;
|
Vector3d position;
|
||||||
Quaternion rotation;
|
Rotation rotation;
|
||||||
|
|
||||||
lock (Lock)
|
lock (Lock)
|
||||||
{
|
{
|
||||||
@ -117,7 +116,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
|
|
||||||
var pitch = (float)vp_double(sender, FloatAttribute.AvatarPitch);
|
var pitch = (float)vp_double(sender, FloatAttribute.AvatarPitch);
|
||||||
var yaw = (float)vp_double(sender, FloatAttribute.AvatarYaw);
|
var yaw = (float)vp_double(sender, FloatAttribute.AvatarYaw);
|
||||||
rotation = Quaternion.CreateFromYawPitchRoll(yaw, pitch, 0);
|
rotation = Rotation.CreateFromTiltYawRoll(pitch, yaw, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualParadiseAvatar? avatar = GetAvatar(session);
|
VirtualParadiseAvatar? avatar = GetAvatar(session);
|
||||||
@ -436,7 +435,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
int session;
|
int session;
|
||||||
string worldName;
|
string worldName;
|
||||||
Vector3d position;
|
Vector3d position;
|
||||||
Quaternion rotation;
|
Rotation rotation;
|
||||||
|
|
||||||
lock (Lock)
|
lock (Lock)
|
||||||
{
|
{
|
||||||
@ -449,7 +448,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
|
|
||||||
float yaw = vp_float(sender, FloatAttribute.TeleportYaw);
|
float yaw = vp_float(sender, FloatAttribute.TeleportYaw);
|
||||||
float pitch = vp_float(sender, FloatAttribute.TeleportPitch);
|
float pitch = vp_float(sender, FloatAttribute.TeleportPitch);
|
||||||
rotation = Quaternion.CreateFromYawPitchRoll(yaw, pitch, 0);
|
rotation = Rotation.CreateFromTiltYawRoll(pitch, yaw, 0);
|
||||||
|
|
||||||
worldName = vp_string(sender, StringAttribute.TeleportWorld);
|
worldName = vp_string(sender, StringAttribute.TeleportWorld);
|
||||||
}
|
}
|
||||||
@ -546,7 +545,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
private async void OnInviteNativeEvent(nint sender)
|
private async void OnInviteNativeEvent(nint sender)
|
||||||
{
|
{
|
||||||
Vector3d position;
|
Vector3d position;
|
||||||
Quaternion rotation;
|
Rotation rotation;
|
||||||
int requestId;
|
int requestId;
|
||||||
int userId;
|
int userId;
|
||||||
string worldName;
|
string worldName;
|
||||||
@ -566,7 +565,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
var pitch = (float)vp_double(sender, FloatAttribute.InvitePitch);
|
var pitch = (float)vp_double(sender, FloatAttribute.InvitePitch);
|
||||||
|
|
||||||
position = new Vector3d(x, y, z);
|
position = new Vector3d(x, y, z);
|
||||||
rotation = Quaternion.CreateFromYawPitchRoll(yaw, pitch, 0);
|
rotation = Rotation.CreateFromTiltYawRoll(pitch, yaw, 0);
|
||||||
|
|
||||||
worldName = vp_string(sender, StringAttribute.InviteWorld);
|
worldName = vp_string(sender, StringAttribute.InviteWorld);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Numerics;
|
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
using VpSharp.Exceptions;
|
using VpSharp.Exceptions;
|
||||||
using VpSharp.Internal;
|
using VpSharp.Internal;
|
||||||
using VpSharp.Internal.NativeAttributes;
|
using VpSharp.Internal.NativeAttributes;
|
||||||
using X10D.Math;
|
|
||||||
using static VpSharp.Internal.NativeMethods;
|
using static VpSharp.Internal.NativeMethods;
|
||||||
|
|
||||||
namespace VpSharp;
|
namespace VpSharp;
|
||||||
@ -179,7 +177,7 @@ public sealed partial class VirtualParadiseClient
|
|||||||
int id;
|
int id;
|
||||||
int time;
|
int time;
|
||||||
int owner;
|
int owner;
|
||||||
Quaternion rotation;
|
Rotation rotation;
|
||||||
Vector3d position;
|
Vector3d position;
|
||||||
|
|
||||||
lock (Lock)
|
lock (Lock)
|
||||||
@ -200,15 +198,12 @@ public sealed partial class VirtualParadiseClient
|
|||||||
|
|
||||||
if (double.IsPositiveInfinity(angle))
|
if (double.IsPositiveInfinity(angle))
|
||||||
{
|
{
|
||||||
rotX = rotX.DegreesToRadians();
|
rotation = Rotation.CreateFromTiltYawRoll(rotX, rotY, rotZ);
|
||||||
rotY = rotY.DegreesToRadians();
|
|
||||||
rotZ = rotZ.DegreesToRadians();
|
|
||||||
rotation = Quaternion.CreateFromYawPitchRoll(rotY, rotX, rotZ);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var axis = new Vector3(rotX, rotY, rotZ);
|
var axis = new Vector3d(rotX, rotY, rotZ);
|
||||||
rotation = Quaternion.CreateFromAxisAngle(axis, angle);
|
rotation = Rotation.CreateFromAxisAngle(axis, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
time = vp_int(sender, IntegerAttribute.ObjectTime);
|
time = vp_int(sender, IntegerAttribute.ObjectTime);
|
||||||
|
@ -2,7 +2,6 @@ using System.Collections.Concurrent;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Numerics;
|
|
||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
@ -218,7 +217,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
public async Task<VirtualParadiseWorld> EnterAsync(string worldName, Vector3d position)
|
public async Task<VirtualParadiseWorld> EnterAsync(string worldName, Vector3d position)
|
||||||
{
|
{
|
||||||
await EnterAsync(worldName).ConfigureAwait(false);
|
await EnterAsync(worldName).ConfigureAwait(false);
|
||||||
await CurrentAvatar!.TeleportAsync(position, Quaternion.Identity).ConfigureAwait(false);
|
await CurrentAvatar!.TeleportAsync(position, Rotation.None).ConfigureAwait(false);
|
||||||
return CurrentWorld!;
|
return CurrentWorld!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +234,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
/// <exception cref="Exception">Connection to the universe server was lost, or connecting to the world failed.</exception>
|
/// <exception cref="Exception">Connection to the universe server was lost, or connecting to the world failed.</exception>
|
||||||
/// <exception cref="WorldNotFoundException">The specified world was not found.</exception>
|
/// <exception cref="WorldNotFoundException">The specified world was not found.</exception>
|
||||||
/// <exception cref="TimeoutException">Connection to the world server timed out.</exception>
|
/// <exception cref="TimeoutException">Connection to the world server timed out.</exception>
|
||||||
public async Task<VirtualParadiseWorld> EnterAsync(string worldName, Vector3d position, Quaternion rotation)
|
public async Task<VirtualParadiseWorld> EnterAsync(string worldName, Vector3d position, Rotation rotation)
|
||||||
{
|
{
|
||||||
await EnterAsync(worldName).ConfigureAwait(false);
|
await EnterAsync(worldName).ConfigureAwait(false);
|
||||||
await CurrentAvatar!.TeleportAsync(position, rotation).ConfigureAwait(false);
|
await CurrentAvatar!.TeleportAsync(position, rotation).ConfigureAwait(false);
|
||||||
@ -257,7 +256,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
public async Task EnterAsync(VirtualParadiseWorld world, Vector3d position)
|
public async Task EnterAsync(VirtualParadiseWorld world, Vector3d position)
|
||||||
{
|
{
|
||||||
await EnterAsync(world).ConfigureAwait(false);
|
await EnterAsync(world).ConfigureAwait(false);
|
||||||
await CurrentAvatar!.TeleportAsync(position, Quaternion.Identity).ConfigureAwait(false);
|
await CurrentAvatar!.TeleportAsync(position, Rotation.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -273,7 +272,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
/// <exception cref="Exception">Connection to the universe server was lost, or connecting to the world failed.</exception>
|
/// <exception cref="Exception">Connection to the universe server was lost, or connecting to the world failed.</exception>
|
||||||
/// <exception cref="WorldNotFoundException">The specified world was not found.</exception>
|
/// <exception cref="WorldNotFoundException">The specified world was not found.</exception>
|
||||||
/// <exception cref="TimeoutException">Connection to the world server timed out.</exception>
|
/// <exception cref="TimeoutException">Connection to the world server timed out.</exception>
|
||||||
public async Task EnterAsync(VirtualParadiseWorld world, Vector3d position, Quaternion rotation)
|
public async Task EnterAsync(VirtualParadiseWorld world, Vector3d position, Rotation rotation)
|
||||||
{
|
{
|
||||||
await EnterAsync(world).ConfigureAwait(false);
|
await EnterAsync(world).ConfigureAwait(false);
|
||||||
await CurrentAvatar!.TeleportAsync(position, rotation).ConfigureAwait(false);
|
await CurrentAvatar!.TeleportAsync(position, rotation).ConfigureAwait(false);
|
||||||
@ -401,7 +400,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
{
|
{
|
||||||
Application = _configuration.Application!,
|
Application = _configuration.Application!,
|
||||||
Name = $"[{_configuration.BotName}]",
|
Name = $"[{_configuration.BotName}]",
|
||||||
Location = new Location(world, Vector3d.Zero, Quaternion.Identity),
|
Location = new Location(world, Vector3d.Zero, Rotation.None),
|
||||||
User = CurrentUser!
|
User = CurrentUser!
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user