From 28926a1507da9ef954ddfa6986e63df7cd5aeac0 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 19 Nov 2024 13:22:59 +0100 Subject: [PATCH] First prototype RoboidSite support working --- .../Networking/NetworkingStarter_Editor.cs | 2 +- .../Scripts/Networking/HumanoidPlayer.cs | 2 +- .../Scripts/Networking/Roboid.meta | 8 + .../Networking/Roboid/HumanoidPlayerRoboid.cs | 578 ++++++++++++++++++ .../Roboid/HumanoidPlayerRoboid.cs.meta | 11 + .../Networking/Roboid/RoboidStarter.cs | 40 ++ .../Networking/Roboid/RoboidStarter.cs.meta | 11 + .../Scripts/Networking/Roboid/Spherical.cs | 53 ++ .../Networking/Roboid/Spherical.cs.meta | 11 + .../Scripts/Targets/FootTarget.cs | 26 +- .../Scripts/Targets/HandTarget.cs | 17 +- .../Scripts/Targets/HeadTarget.cs | 35 +- .../Scripts/Targets/HipsTarget.cs | 19 +- .../Scripts/Targets/HumanoidTarget.cs | 3 +- Runtime/Tools/Networking/NetworkingStarter.cs | 4 +- 15 files changed, 794 insertions(+), 26 deletions(-) create mode 100644 Runtime/HumanoidControl/Scripts/Networking/Roboid.meta create mode 100644 Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs create mode 100644 Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs.meta create mode 100644 Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs create mode 100644 Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs.meta create mode 100644 Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs create mode 100644 Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs.meta diff --git a/Editor/Tools/Networking/NetworkingStarter_Editor.cs b/Editor/Tools/Networking/NetworkingStarter_Editor.cs index 70ae988..131c015 100644 --- a/Editor/Tools/Networking/NetworkingStarter_Editor.cs +++ b/Editor/Tools/Networking/NetworkingStarter_Editor.cs @@ -34,7 +34,7 @@ namespace Passer.Humanoid { public override void OnInspectorGUI() { serializedObject.Update(); -#if !hNW_UNET && !hNW_PHOTON && !hNW_MIRROR && !hNW_BOLT +#if !hNW_UNET && !hNW_PHOTON && !hNW_MIRROR && !hNW_BOLT && !hNW_ROBOID EditorGUILayout.HelpBox("Networking Support is disabled. Check Preferences to enable it.", MessageType.Warning); #else diff --git a/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs b/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs index 53d14df..0df427c 100644 --- a/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs +++ b/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs @@ -6,7 +6,7 @@ using UnityEngine; namespace Passer.Humanoid { #pragma warning disable 0618 -#if hNW_UNET || hNW_MIRROR || hNW_PHOTON || hNW_BOLT +#if hNW_UNET || hNW_MIRROR || hNW_PHOTON || hNW_BOLT || hNW_ROBOID public partial class HumanoidPlayer { [SerializeField] diff --git a/Runtime/HumanoidControl/Scripts/Networking/Roboid.meta b/Runtime/HumanoidControl/Scripts/Networking/Roboid.meta new file mode 100644 index 0000000..f82ef63 --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/Roboid.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c951b29def0f4d240a2a7bef87502741 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs b/Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs new file mode 100644 index 0000000..bce4f2e --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs @@ -0,0 +1,578 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using UnityEngine; +using System.Runtime.Serialization; + + +#if hNW_ROBOID + +using Passer.LinearAlgebra; + +namespace Passer.Humanoid { + + public partial class HumanoidPlayer : MonoBehaviour, IHumanoidNetworking { + + [SerializeField] + protected float _sendRate = 25; + public float sendRate { + get { return _sendRate; } + } + + [SerializeField] + protected bool _createLocalRemotes = false; + public bool createLocalRemotes { + get { return _createLocalRemotes; } + set { _createLocalRemotes = value; } + } + + public int nssPort = 7681; + protected UdpClient udpClient; + protected IPEndPoint endPoint; + protected object obj; + protected AsyncCallback receiveCallback; + ConcurrentQueue messageQueue = new ConcurrentQueue(); + + public byte networkId; + + #region Dummy Interface + + public void Send(bool b) { } + public void Send(byte b) { } + public void Send(int x) { } + public void Send(float f) { } + public void Send(Vector3 v) { } + public void Send(Quaternion q) { } + + public bool ReceiveBool() { + return false; + } + public byte ReceiveByte() { + return 0; + } + public int ReceiveInt() { + return 0; + } + public float ReceiveFloat() { + return 0; + } + public Vector3 ReceiveVector3() { + return Vector3.zero; + } + public Quaternion ReceiveQuaternion() { + return Quaternion.identity; + } + + public ulong GetObjectIdentity(GameObject obj) { + return 0; + } + public GameObject GetGameObject(ulong objIdentity) { + return this.gameObject; + } + + public void InstantiateHumanoid(HumanoidControl humanoid) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Send Instantiate Humanoid " + humanoid.humanoidId); + + HumanoidNetworking.InstantiateHumanoid instantiateHumanoid = new HumanoidNetworking.InstantiateHumanoid(humanoid); + if (createLocalRemotes) + this.Receive(instantiateHumanoid); + } + public void DestroyHumanoid(HumanoidControl humanoid) { } + public void Grab(HandTarget handTarget, GameObject obj, bool rangeCheck, HandTarget.GrabType grabType = HandTarget.GrabType.HandGrab) { } + public void LetGo(HandTarget handTarget) { } + public void ChangeAvatar(HumanoidControl humanoid, string avatarPrefabName, string possessionLocation = null) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + Debug.Log(humanoid.nwId + ": Change Avatar: " + avatarPrefabName); + + HumanoidNetworking.ChangeAvatar changeAvatar = new HumanoidNetworking.ChangeAvatar(humanoid, avatarPrefabName, possessionLocation); + if (createLocalRemotes) + this.Receive(changeAvatar); + } + + public void SyncTrackingSpace(HumanoidControl humanoid) { } + public void ReenableNetworkSync(GameObject obj) { } + public void DisableNetworkSync(GameObject obj) { } + + public void DebugLog(string s) { + Debug.Log(s); + } + public void DebugWarning(string s) { + Debug.LogWarning(s); + } + public void DebugError(string s) { + Debug.LogError(s); + } + + public HumanoidNetworking.Smoothing smoothing => HumanoidNetworking.Smoothing.None; + + private bool _isLocal; + public bool isLocal => _isLocal; // may need to implement this + + public ulong nwId => 0; + + public HumanoidNetworking.HumanoidPose lastHumanoidPose { get => null; set { return; } } + + public List humanoids { get; set; } + + #endregion Dummy Interface + + protected virtual void Awake() { + mInstance = this; + + GameObject.DontDestroyOnLoad(this.gameObject); + humanoids = HumanoidNetworking.FindLocalHumanoids(); + + for (int i = 0; i < humanoids.Count; i++) { + HumanoidControl humanoid = humanoids[i]; + if (humanoid.isRemote) + continue; + + humanoid.humanoidNetworking = this; + } + + endPoint = new IPEndPoint(IPAddress.Any, nssPort + 3); + udpClient = new UdpClient(endPoint); + receiveCallback = new AsyncCallback(Receiver); + udpClient.BeginReceive(receiveCallback, obj); + } + + protected void OnApplicationQuit() { + if (udpClient != null) { + udpClient.Client.Close(); + udpClient.Close(); + udpClient = null; + } + } + + #region Update + + float lastSend; + + protected virtual void LateUpdate() { + while (messageQueue.TryDequeue(out HumanoidNetworking.IMessage msg)) { + ProcessMessage(msg); + } + + if (Time.time > lastSend + 1 / sendRate) { + if (humanoids != null) { + foreach (HumanoidControl humanoid in humanoids) { + if (!humanoid.isRemote) { + UpdateHumanoidPose(humanoid); + } + } + } + lastSend = Time.time; + } + } + + protected virtual void ProcessMessage(HumanoidNetworking.IMessage msg) { + switch (msg) { + case NetworkIdMsg networkId: + ProcessNetworkId(networkId); + break; + } + } + + void Receiver(IAsyncResult result) { + // Take care of buffered messages after the client has been closed + if (udpClient == null || udpClient.Client.Connected == false) + return; + + byte[] data = (udpClient.EndReceive(result, ref endPoint)); + + ReceivePacket(data); + + udpClient.BeginReceive(receiveCallback, obj); + } + + void ReceivePacket(byte[] data) { + byte msgId = data[0]; + switch (msgId) { + case 0xA1: // (161) Network Id + this.ReceiveNetworkId(data); break; + } + + } + + #endregion Update + + #region NetworkId + + public class NetworkIdMsg : HumanoidNetworking.IMessage { + public const byte msgId = 0xA1; + public byte networkId = 0; + + public NetworkIdMsg(byte networkId) { + this.networkId = networkId; + } + public NetworkIdMsg(byte[] data) : base(data) { } + + public override byte[] Serialize() { + MemoryStream ms = new(); + BinaryWriter bw = new(ms); + bw.Write(msgId); + bw.Write(this.networkId); // Thing Id + byte[] data = ms.ToArray(); + return data; + } + public override void Deserialize(byte[] data) { + base.Deserialize(data); + this.networkId = (byte)data[1]; + } + } + + public void ReceiveNetworkId(byte[] data) { + NetworkIdMsg msg = new(data); + this.networkId = msg.networkId; + + messageQueue.Enqueue(msg); + } + + private void ProcessNetworkId(NetworkIdMsg msg) { + GameObject networkingObj = this.GetGameObject(msg.networkId); + if (networkingObj == null) { + if (this.debug <= HumanoidNetworking.DebugLevel.Error) + this.DebugLog("Could not find Networking for Instantiate Humanoid " + msg.networkId + "/0"); + return; + } + HumanoidControl remoteHumanoid = humanoids[0]; //FindRemoteHumanoid(humanoids, 0); + if (remoteHumanoid == null) { + if (debug <= HumanoidNetworking.DebugLevel.Warning) + DebugLog("Remote Humanoid " + msg.networkId + "/" + 0 + "not found"); + return; + } + + SendThing(remoteHumanoid); + SendName(remoteHumanoid, 0, "Humanoid"); + SendModel(remoteHumanoid, "https://gitlab.passervr.com/passer/models/humanoid/-/raw/main/MakeHumanPasserMedium.glb?ref_type=heads&inline=false"); + + SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.upperLeg); + SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.lowerLeg); + SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.foot); + SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.toes); + + SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.upperLeg); + SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.lowerLeg); + SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.foot); + SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.toes); + } + + #endregion + + #region Thing + + protected class ThingMsg : HumanoidNetworking.IMessage { + private const byte msgId = 0x80; + public const byte length = 3; + public byte thingId; + public byte thingType; + + public ThingMsg(byte thingId, byte thingType) { + this.thingId = thingId; + this.thingType = thingType; + } + public ThingMsg(byte[] data) : base(data) { } + + public override byte[] Serialize() { + byte[] data = new byte[3]; + data[0] = msgId; + data[1] = thingId; + data[2] = thingType; + return data; + } + public override void Deserialize(byte[] data) { + try { + uint ix = 0; + thingId = data[ix++]; + thingType = data[ix++]; + } + catch { } + } + } + + public void SendThing(HumanoidControl humanoid) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) + Debug.Log("Send Thing " + humanoid.humanoidId + " nwId: " + humanoid.nwId); + + ThingMsg thingMsg = new(0, 1); + + if (udpClient != null) { + byte[] data = thingMsg.Serialize(); + udpClient.Send(data, data.Length, "127.0.0.1", nssPort); + } + } + + #endregion Thing + + #region SubThing + + protected class SubThingMsg : HumanoidNetworking.IMessage { + private const byte msgId = 0x12; // (18) + public const byte length = 3 + 4; + public byte thingId; + public byte parentId; + readonly Vector3 position; + + public SubThingMsg(byte thingId, byte parentId, Vector3 position) { + this.thingId = thingId; + this.parentId = parentId; + this.position = position; + } + public SubThingMsg(byte[] data) : base(data) { } + + public override byte[] Serialize() { + byte[] data = new byte[7]; + data[0] = msgId; + data[1] = thingId; + data[2] = parentId; + + data[3] = 0; + data[4] = 0; + data[5] = 0; + data[6] = 0; + return data; + } + //public override void Deserialize(byte[] data) { + // try { + // uint ix = 0; + // thingId = data[ix++]; + // thingType = data[ix++]; + // } + // catch { } + //} + } + + public void SendSubThing(HumanoidControl humanoid, HumanoidTarget.TargetedBone bone) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) + Debug.Log("Send SubThing " + humanoid.humanoidId + " nwId: " + humanoid.nwId); + + SubThingMsg thingMsg = new((byte)bone.boneId, (byte)bone.parent.boneId, bone.bone.transform.position); + + if (udpClient != null) { + byte[] data = thingMsg.Serialize(); + udpClient.Send(data, data.Length, "127.0.0.1", nssPort); + } + + SendName(humanoid, (byte)bone.boneId, bone.bone.transform.name); + } + + #endregion + + #region Name + + public class NameMsg : HumanoidNetworking.IMessage { + public const byte msgId = 0x91; // (145) Name + public byte networkId = 0; + public byte thingId; + public byte len; + public string name; + + public NameMsg(byte thingId, string name) { + this.thingId = thingId; + this.name = name; + } + public NameMsg(byte[] data) : base(data) { } + + public override byte[] Serialize() { + MemoryStream ms = new(); + BinaryWriter bw = new(ms); + bw.Write(msgId); // 145 Name Msg + bw.Write((byte)thingId); // Thing Id + bw.Write((byte)name.Length); + + for (int ix = 0; ix < name.Length; ix++) + bw.Write(name[ix]); + + byte[] data = ms.ToArray(); + return data; + } + public override void Deserialize(byte[] data) { + uint ix = 0; + this.thingId = data[ix++]; + int strlen = data[ix++]; + this.name = System.Text.Encoding.UTF8.GetString(data, (int)ix, strlen); + } + } + + public void SendName(HumanoidControl humanoid, byte thingId, string name) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) + Debug.Log("Send Name " + humanoid.humanoidId + " nwId: " + humanoid.nwId); + + NameMsg nameMsg = new(thingId, name); // humanoid.name; + + if (udpClient != null) { + byte[] data = nameMsg.Serialize(); + udpClient.Send(data, data.Length, "127.0.0.1", nssPort); + } + } + + #endregion + + #region Model + + class ModelUrlMsg : HumanoidNetworking.IMessage { + public const byte msgId = 0x90; // (144) Model URL + public byte objectId; + public Vector3 position; + public float scale; + public string url; + + public ModelUrlMsg(string url) { + this.url = url; + } + public ModelUrlMsg(byte[] data) : base(data) { } + + public override byte[] Serialize() { + MemoryStream ms = new(); + BinaryWriter bw = new(ms); + bw.Write(msgId); // 145 Name Msg + bw.Write((byte)0x00); // Thing Id + + bw.Write((byte)0x00); // Dummy position + bw.Write((byte)0x00); + bw.Write((byte)0x00); + bw.Write((byte)0x00); + + SendFloat16(bw, 1.0f); + + bw.Write((byte)url.Length); + + for (int ix = 0; ix < url.Length; ix++) + bw.Write(url[ix]); + + byte[] data = ms.ToArray(); + return data; + } + //public override void Deserialize(byte[] data) { + // uint ix = 0; + // this.objectId = data[ix++]; + // //this.position = ReceiveVector3(data, ref ix); + // this.position = ReceiveSpherical(data, ref ix); + // this.scale = ReceiveFloat16(data, ref ix); + // int strlen = data[ix++]; + // url = System.Text.Encoding.UTF8.GetString(data, (int)ix, strlen); + //} + } + + public void SendModel(HumanoidControl humanoid, string url) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) + Debug.Log("Send Name " + humanoid.humanoidId + " nwId: " + humanoid.nwId); + + ModelUrlMsg msg = new(url); // humanoid.name; + + if (udpClient != null) { + byte[] data = msg.Serialize(); + udpClient.Send(data, data.Length, "127.0.0.1", nssPort); + } + } + + #endregion Model + + #region Pose + + [Serializable] + public class RoboidBonePose : HumanoidNetworking.HumanoidPose { + private readonly byte msgId = 0x10; + readonly byte boneId; + readonly Quat32 boneOrientation; + + public RoboidBonePose(HumanoidTarget.TargetedBone targetedBone) { + this.boneId = (byte)targetedBone.boneId; + this.boneOrientation = new Quat32(targetedBone.bone.transform.localRotation); + } + + public override byte[] Serialize() { + byte[] data = new byte[11]; + data[0] = msgId; + data[1] = boneId; + data[2] = 0x03; // Pose_orientation + + //data[3][4][5][6] are 0 + + data[7] = boneOrientation.qx; + data[8] = boneOrientation.qy; + data[9] = boneOrientation.qz; + data[10] = boneOrientation.qw; + return data; + } + } + + + [Serializable] + public class RoboidPose : HumanoidNetworking.HumanoidPose { + readonly Quat32 headOrientation; + + public RoboidPose(HumanoidControl humanoid) { + headOrientation = new Quat32(humanoid.headTarget.head.bone.transform.rotation); + } + + public override byte[] Serialize() { + MemoryStream ms = new(); + BinaryWriter bw = new(ms); + bw.Write((byte)0x10); // PoseMsg + bw.Write((byte)this.head.boneId); // Thing Id + bw.Write((byte)0x03); // Pose_Orientation + + bw.Write((byte)0x00); // Dummy data + bw.Write((byte)0x00); + bw.Write((byte)0x00); + bw.Write((byte)0x00); + + SendQuat32(bw, headOrientation); + + byte[] data = ms.ToArray(); + return data; + } + } + + public virtual void UpdateHumanoidPose(HumanoidControl humanoid) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) + Debug.Log("Send Pose Humanoid " + humanoid.humanoidId + " nwId: " + humanoid.nwId); + + RoboidPose humanoidPose = new(humanoid); + if (createLocalRemotes) + this.Receive(humanoidPose); + + if (udpClient != null) { + byte[] data = humanoidPose.Serialize(); + udpClient.Send(data, data.Length, "127.0.0.1", nssPort); + } + SendBone(humanoid.leftFootTarget.upperLeg); + SendBone(humanoid.leftFootTarget.lowerLeg); + SendBone(humanoid.leftFootTarget.foot); + + SendBone(humanoid.rightFootTarget.upperLeg); + SendBone(humanoid.rightFootTarget.lowerLeg); + SendBone(humanoid.rightFootTarget.foot); + } + + private void SendBone(HumanoidTarget.TargetedBone bone) { + RoboidBonePose bonePose = new(bone); + byte[] buffer = bonePose.Serialize(); + udpClient.Send(buffer, buffer.Length, "127.0.0.1", nssPort); + } + + #endregion Pose + + #region Send + + static void SendQuat32(BinaryWriter bw, Quat32 q) { + bw.Write((byte)q.qx); + bw.Write((byte)q.qy); + bw.Write((byte)q.qz); + bw.Write((byte)q.qw); + } + + static void SendFloat16(BinaryWriter bw, float f) { + bw.Write((byte)0x3C); // Dummy value 1 + bw.Write((byte)0x00); + } + + #endregion Send + } +} +#endif \ No newline at end of file diff --git a/Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs.meta b/Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs.meta new file mode 100644 index 0000000..5d760a9 --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/Roboid/HumanoidPlayerRoboid.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3438587d9f577c241a381273590f7f70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs b/Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs new file mode 100644 index 0000000..8df5756 --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs @@ -0,0 +1,40 @@ +using System.IO; +using System.Net; +using System.Net.Sockets; +using UnityEngine; + +namespace Passer { + + public class RoboidStarter : INetworkingStarter { + + //public int nssPort = 7681; + //protected UdpClient udpClient; + //protected IPEndPoint endPoint; + //protected Stream dataStream; + + GameObject INetworkingStarter.GetHumanoidPrefab() { + GameObject humanoidPrefab = Resources.Load("HumanoidPlayer"); + return humanoidPrefab; + } + + void INetworkingStarter.StartClient(NetworkingStarter nwStarter) { + ((INetworkingStarter)this).StartClient(nwStarter, nwStarter.roomName, nwStarter.gameVersion); + } + + void INetworkingStarter.StartClient(NetworkingStarter nwStarter, string roomName, int gameVersion) { + //endPoint = new IPEndPoint(IPAddress.Any, nssPort); + //udpClient = new UdpClient(endPoint); + + GameObject humanoidPrefab = Resources.Load("HumanoidPlayer"); + GameObject.Instantiate(humanoidPrefab); + } + + void INetworkingStarter.StartHost(NetworkingStarter nwStarter) { + ((INetworkingStarter)this).StartClient(nwStarter); + } + + void INetworkingStarter.StopClient() { + } + } + +} \ No newline at end of file diff --git a/Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs.meta b/Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs.meta new file mode 100644 index 0000000..a7bc8fa --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/Roboid/RoboidStarter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f298f6b069bcb040ac8bcf621c853b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs b/Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs new file mode 100644 index 0000000..19b246f --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +namespace Passer.LinearAlgebra { + + public class Spherical16 { + + public float distance; + public float horizontal; + public float vertical; + + public Spherical16(float distance, float horizontal = 0, float vertical = 0) { + this.distance = distance; + this.horizontal = horizontal; + this.vertical = vertical; + } + + public static Spherical16 FromVector3(Vector3 v) { + float distance = v.magnitude; + if (distance == 0.0f) { + return new Spherical16(distance); + } + else { + float verticalAngle = Mathf.PI / 2 - Mathf.Acos(v.y / distance) * Mathf.Rad2Deg; + float horizontalAngle = Mathf.Atan2(v.x, v.z) * Mathf.Rad2Deg; + return new Spherical16(distance, horizontalAngle, verticalAngle); + } + } + } + + public class Quat32 { + public byte qx; + public byte qy; + public byte qz; + public byte qw; + + public Quat32(Quaternion q) { + int qx = (int)(q.x * 127 + 128); + int qy = (int)(q.y * 127 + 128); + int qz = (int)(q.z * 127 + 128); + int qw = (int)(q.w * 255); + if (q.w < 0) { + qx = -qx; + qy = -qy; + qz = -qz; + qw = -qw; + } + this.qx = (byte)(qx); + this.qy = (byte)(qy); + this.qz = (byte)(qz); + this.qw = (byte)(qw); + } + } +} \ No newline at end of file diff --git a/Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs.meta b/Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs.meta new file mode 100644 index 0000000..53d3cd2 --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/Roboid/Spherical.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 79bdc65d83f2c8e43bac904e283c6c46 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/HumanoidControl/Scripts/Targets/FootTarget.cs b/Runtime/HumanoidControl/Scripts/Targets/FootTarget.cs index d492d67..f61815d 100644 --- a/Runtime/HumanoidControl/Scripts/Targets/FootTarget.cs +++ b/Runtime/HumanoidControl/Scripts/Targets/FootTarget.cs @@ -63,6 +63,12 @@ namespace Passer.Humanoid { lowerLeg = new TargetedLowerLegBone(this); foot = new TargetedFootBone(this); toes = new TargetedToesBone(this); + subTargets = new TargetedBone[] { + upperLeg, + lowerLeg, + foot, + toes + }; this.isLeft = isLeft; this.side = isLeft ? Side.Left : Side.Right; @@ -120,9 +126,9 @@ namespace Passer.Humanoid { #if hVIVETRACKER public ViveTrackerLeg viveTracker = new ViveTrackerLeg(); #endif -//#if hNEURON -// public PerceptionNeuronLeg neuron = new PerceptionNeuronLeg(); -//#endif + //#if hNEURON + // public PerceptionNeuronLeg neuron = new PerceptionNeuronLeg(); + //#endif #if hKINECT1 public Kinect1Leg kinect1 = new Kinect1Leg(); #endif @@ -200,6 +206,8 @@ namespace Passer.Humanoid { get { return foot; } } + private TargetedBone[] subTargets; + #region UpperLeg public TargetedUpperLegBone upperLeg; @@ -210,6 +218,7 @@ namespace Passer.Humanoid { public TargetedUpperLegBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.lowerLeg) { this.footTarget = footTarget; + this.parent = footTarget.humanoid.hipsTarget.hips; } public override void Init() { @@ -254,6 +263,7 @@ namespace Passer.Humanoid { public TargetedLowerLegBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.foot) { this.footTarget = footTarget; + this.parent = footTarget.upperLeg; } public override void Init() { @@ -289,6 +299,7 @@ namespace Passer.Humanoid { #endregion #region Foot + public TargetedFootBone foot; [System.Serializable] @@ -297,6 +308,7 @@ namespace Passer.Humanoid { public TargetedFootBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.toes) { this.footTarget = footTarget; + this.parent = footTarget.lowerLeg; } public override void Init() { @@ -368,6 +380,7 @@ namespace Passer.Humanoid { public TargetedToesBone(FootTarget footTarget) : base(footTarget.humanoid) { this.footTarget = footTarget; + this.parent = footTarget.foot; } public override void Init() { @@ -801,12 +814,13 @@ namespace Passer.Humanoid { } footTarget = footTargetTransform.GetComponent(); - if (footTarget == null) { + if (footTarget == null) footTarget = footTargetTransform.gameObject.AddComponent(); - footTarget.Constructor(humanoid, isLeft); - } } + if (footTarget.subTargets == null) + footTarget.Constructor(humanoid, isLeft); + if (isLeft) humanoid.leftFootTarget = footTarget; else diff --git a/Runtime/HumanoidControl/Scripts/Targets/HandTarget.cs b/Runtime/HumanoidControl/Scripts/Targets/HandTarget.cs index 4e8dd53..2cf1d53 100644 --- a/Runtime/HumanoidControl/Scripts/Targets/HandTarget.cs +++ b/Runtime/HumanoidControl/Scripts/Targets/HandTarget.cs @@ -402,6 +402,13 @@ namespace Passer.Humanoid { public TargetedShoulderBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.upperArm) { this.handTarget = handTarget; + if (handTarget.humanoid == null || handTarget.humanoid.hipsTarget == null) + this.parent = null; + else + this.parent = (handTarget.humanoid.hipsTarget.chest.bone.transform != null) ? + handTarget.humanoid.hipsTarget.chest : + handTarget.humanoid.hipsTarget.hips; + bone.jointLimitations = true; } @@ -471,6 +478,7 @@ namespace Passer.Humanoid { public TargetedUpperArmBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.forearm) { this.handTarget = handTarget; + this.parent = handTarget.shoulder; } public override void Init() { @@ -527,6 +535,7 @@ namespace Passer.Humanoid { public TargetedForearmBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.hand) { this.handTarget = handTarget; + this.parent = handTarget.upperArm; } public override void Init() { @@ -589,6 +598,7 @@ namespace Passer.Humanoid { public TargetedHandBone(HandTarget handTarget) : base(handTarget.humanoid) { this.handTarget = handTarget; + this.parent = handTarget.forearm; } public override void Init() { @@ -1372,12 +1382,13 @@ namespace Passer.Humanoid { } handTarget = handTargetTransform.GetComponent(); - if (handTarget == null) { + if (handTarget == null) handTarget = handTargetTransform.gameObject.AddComponent(); - handTarget.Constructor(humanoid, isLeft); - } } + if (handTarget.subTargets == null) + handTarget.Constructor(humanoid, isLeft); + if (isLeft) humanoid.leftHandTarget = handTarget; else diff --git a/Runtime/HumanoidControl/Scripts/Targets/HeadTarget.cs b/Runtime/HumanoidControl/Scripts/Targets/HeadTarget.cs index b0364d3..b260faf 100644 --- a/Runtime/HumanoidControl/Scripts/Targets/HeadTarget.cs +++ b/Runtime/HumanoidControl/Scripts/Targets/HeadTarget.cs @@ -71,10 +71,20 @@ namespace Passer.Humanoid { /// The humanoid for this head target public void Constructor(HumanoidControl humanoid) { this.humanoid = humanoid; - neck = new TargetedNeckBone(this); - head = new TargetedHeadBone(this); + this.neck = new TargetedNeckBone(this); + this.head = new TargetedHeadBone(this); #if hFACE face = new FaceTarget(this); + subTargets = new TargetedBone[] { + neck, + head, + face + }; +#else + subTargets = new TargetedBone[] { + neck, + head + }; #endif } @@ -306,6 +316,7 @@ namespace Passer.Humanoid { public override TargetedBone main { get { return head; } } + private TargetedBone[] subTargets; #region Head @@ -313,10 +324,11 @@ namespace Passer.Humanoid { [System.Serializable] public class TargetedHeadBone : TargetedBone { - private HeadTarget headTarget; + readonly private HeadTarget headTarget; public TargetedHeadBone(HeadTarget headTarget) : base(headTarget.humanoid) { this.headTarget = headTarget; + this.parent = headTarget.neck; boneId = Bone.Head; @@ -404,10 +416,17 @@ namespace Passer.Humanoid { [System.Serializable] public class TargetedNeckBone : TargetedBone { - public HeadTarget headTarget; + readonly private HeadTarget headTarget; public TargetedNeckBone(HeadTarget headTarget) : base(headTarget.humanoid) { this.headTarget = headTarget; + if (headTarget.humanoid == null || headTarget.humanoid.hipsTarget == null) + this.parent = null; + else + this.parent = (headTarget.humanoid.hipsTarget.chest.bone.transform != null) ? + headTarget.humanoid.hipsTarget.chest : + headTarget.humanoid.hipsTarget.hips; + boneId = Bone.Neck; bone.minAngles = minNeckAngles; @@ -853,13 +872,13 @@ namespace Passer.Humanoid { } headTarget = headTargetTransform.GetComponent(); - if (headTarget == null) { + if (headTarget == null) headTarget = headTargetTransform.gameObject.AddComponent(); - headTarget.Constructor(humanoid); - } - humanoid.headTarget = headTarget; } + if (headTarget.subTargets == null) + headTarget.Constructor(humanoid); + humanoid.headTarget = headTarget; } diff --git a/Runtime/HumanoidControl/Scripts/Targets/HipsTarget.cs b/Runtime/HumanoidControl/Scripts/Targets/HipsTarget.cs index 79a17fd..ae90bfb 100644 --- a/Runtime/HumanoidControl/Scripts/Targets/HipsTarget.cs +++ b/Runtime/HumanoidControl/Scripts/Targets/HipsTarget.cs @@ -47,9 +47,14 @@ namespace Passer.Humanoid { /// The humanoid for this hips target public void Constructor(HumanoidControl humanoid) { this.humanoid = humanoid; - chest = new TargetedChestBone(this); - spine = new TargetedSpineBone(this); hips = new TargetedHipsBone(this); + spine = new TargetedSpineBone(this); + chest = new TargetedChestBone(this); + subTargets = new TargetedBone[] { + hips, + spine, + chest + }; } public bool simpleSpineIK => newSpineIK; @@ -161,6 +166,7 @@ namespace Passer.Humanoid { public override TargetedBone main { get { return hips; } } + private TargetedBone[] subTargets; #region Chest @@ -172,6 +178,7 @@ namespace Passer.Humanoid { public TargetedChestBone(HipsTarget hipsTarget) : base(hipsTarget.humanoid) { this.hipsTarget = hipsTarget; + this.parent = hipsTarget.spine; boneId = Bone.Chest; } @@ -226,6 +233,7 @@ namespace Passer.Humanoid { public TargetedSpineBone(HipsTarget hipsTarget) : base(hipsTarget.humanoid) { this.hipsTarget = hipsTarget; + this.parent = hipsTarget.hips; boneId = Bone.Spine; } @@ -621,12 +629,13 @@ namespace Passer.Humanoid { } hipsTarget = hipsTargetTransform.GetComponent(); - if (hipsTarget == null) { + if (hipsTarget == null) hipsTarget = hipsTargetTransform.gameObject.AddComponent(); - hipsTarget.Constructor(humanoid); - } } + if (hipsTarget.subTargets == null) + hipsTarget.Constructor(humanoid); + humanoid.hipsTarget = hipsTarget; } diff --git a/Runtime/HumanoidControl/Scripts/Targets/HumanoidTarget.cs b/Runtime/HumanoidControl/Scripts/Targets/HumanoidTarget.cs index 544ec34..7c9be52 100644 --- a/Runtime/HumanoidControl/Scripts/Targets/HumanoidTarget.cs +++ b/Runtime/HumanoidControl/Scripts/Targets/HumanoidTarget.cs @@ -421,7 +421,8 @@ namespace Passer.Humanoid { public TargetedBone(HumanoidControl humanoid, TargetedBone _nextBone) { if (humanoid == null) throw new System.Exception("Humanoid may not be null"); - nextBone = _nextBone; + this.humanoid = humanoid; + this.nextBone = _nextBone; } public virtual void Init() { } diff --git a/Runtime/Tools/Networking/NetworkingStarter.cs b/Runtime/Tools/Networking/NetworkingStarter.cs index c888b65..6aca3be 100644 --- a/Runtime/Tools/Networking/NetworkingStarter.cs +++ b/Runtime/Tools/Networking/NetworkingStarter.cs @@ -31,7 +31,9 @@ namespace Passer { #endif { public bool autoStart = true; -#if hNW_UNET +#if hNW_ROBOID + protected INetworkingStarter starter = new RoboidStarter(); +#elif hNW_UNET protected INetworkingStarter starter = new UnetStarter(); #elif hNW_PHOTON protected INetworkingStarter starter = new PunStarter();