822 lines
33 KiB
C#
822 lines
33 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
using GLTFast;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
|
|
|
|
#if hNW_ROBOID
|
|
|
|
using Passer.Control;
|
|
using Passer.LinearAlgebra;
|
|
|
|
namespace Passer.Humanoid {
|
|
|
|
public partial class HumanoidPlayer : MonoBehaviour, IHumanoidNetworking { //}, ISiteServer {
|
|
|
|
[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 sitePort = 7681;
|
|
public string siteAddress = "127.0.0.1";
|
|
protected UdpClient udpClient;
|
|
protected IPEndPoint endPoint;
|
|
protected object obj;
|
|
protected AsyncCallback receiveCallback;
|
|
protected Client client;
|
|
//ConcurrentQueue<HumanoidNetworking.IMessage> messageQueue = new ConcurrentQueue<HumanoidNetworking.IMessage>();
|
|
protected Stream dataStream;
|
|
|
|
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<HumanoidControl> humanoids { get; set; }
|
|
|
|
#endregion Dummy Interface
|
|
|
|
public class HumanoidClient : Client {
|
|
readonly HumanoidPlayer player;
|
|
|
|
public HumanoidClient(UdpClient udpClient, string ipAddress, int port, HumanoidPlayer player) {
|
|
this.ipAddress = ipAddress;
|
|
this.port = port;
|
|
this.udpClient = udpClient;
|
|
this.player = player;
|
|
clients.Add(this);
|
|
}
|
|
|
|
protected override void ProcessNetworkId(NetworkIdMsg msg) {
|
|
if (this.networkId == msg.networkId)
|
|
return;
|
|
|
|
this.networkId = msg.networkId;
|
|
player.ProcessNetworkId(this, msg);
|
|
}
|
|
|
|
protected override void ProcessModelUrl(ModelUrlMsg msg) {
|
|
int ix = msg.url.LastIndexOf(".");
|
|
if (ix < 0)
|
|
return;
|
|
|
|
string extension = msg.url.Substring(msg.url.LastIndexOf("."));
|
|
string extension3 = extension.Substring(0, 4);
|
|
string extension4 = extension.Substring(0, 5);
|
|
if (extension4 == ".gltf" || extension3 == ".glb") {
|
|
player.ProcessGltfModel(msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
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, sitePort + 3);
|
|
udpClient = new UdpClient(endPoint);
|
|
receiveCallback = new System.AsyncCallback(result => ReceiveUDP(client, result));
|
|
udpClient.BeginReceive(receiveCallback, obj);
|
|
client = new HumanoidClient(udpClient, siteAddress, sitePort, this);
|
|
|
|
//
|
|
//endpoint = new IPEndPoint(IPAddress.Any, sitePort);
|
|
//udpClient = new UdpClient(sitePort);
|
|
|
|
//DebugLog($"Start receiving on port {sitePort}");
|
|
dataStream = new EchoStream();
|
|
//client = newClient ? Client.NewUDPClient(udpClient, endpoint.Address.ToString(), endpoint.Port) : Client.clients[0];
|
|
//udpClient.BeginReceive(new System.AsyncCallback(result => ReceiveUDP(client, result)), null);
|
|
Task task = Task.Run(() => SiteServer.ReceiveData(dataStream, client));
|
|
}
|
|
|
|
protected void ReceiveUDP(Client client, IAsyncResult result) {
|
|
if (udpClient == null)
|
|
return;
|
|
|
|
if (udpClient.Client.Connected) {
|
|
try {
|
|
byte[] data = udpClient.EndReceive(result, ref endPoint);
|
|
dataStream.WriteByte((byte)data.Length);
|
|
dataStream.Write(data, 0, data.Length);
|
|
if (client.ipAddress == null) {
|
|
client.ipAddress = endPoint.Address.ToString();
|
|
client.port = endPoint.Port;
|
|
// I thing sending now is too soon, we are currenlty processing a message...
|
|
//SendNetworkId(client);
|
|
//if (string.IsNullOrEmpty(sceneUrl) == false)
|
|
// SendModelUrl(client, sceneUrl);
|
|
}
|
|
}
|
|
catch (Exception _) {
|
|
Debug.Log("connection error");
|
|
}
|
|
}
|
|
else {
|
|
Debug.Log("Client disconnected");
|
|
}
|
|
udpClient.BeginReceive(new System.AsyncCallback(result => ReceiveUDP(client, result)), null);
|
|
}
|
|
|
|
protected void OnApplicationQuit() {
|
|
if (udpClient != null) {
|
|
udpClient.Client.Close();
|
|
udpClient.Close();
|
|
udpClient = null;
|
|
}
|
|
}
|
|
|
|
#region Update
|
|
|
|
float lastSend;
|
|
const float clientMsgInterval = 3;
|
|
float lastClientMsg = -clientMsgInterval;
|
|
|
|
protected virtual void LateUpdate() {
|
|
foreach (Client client in Client.clients) {
|
|
if (client is HumanoidClient humanoidClient) {
|
|
while (humanoidClient.messageQueue.TryDequeue(out Passer.Control.IMessage msg))
|
|
humanoidClient.ProcessMessage(msg);
|
|
}
|
|
}
|
|
|
|
if (Time.time > lastSend + 1 / sendRate) {
|
|
if (humanoids != null) {
|
|
foreach (HumanoidControl humanoid in humanoids) {
|
|
if (!humanoid.isRemote) {
|
|
UpdateHumanoidPose(humanoid);
|
|
}
|
|
}
|
|
}
|
|
lastSend = Time.time;
|
|
}
|
|
if (Time.time > lastClientMsg + clientMsgInterval) {
|
|
SendClientMsg(humanoids[0]); // We just need it for the networkId
|
|
lastClientMsg = Time.time;
|
|
}
|
|
}
|
|
|
|
#endregion Update
|
|
|
|
#region Client
|
|
|
|
//class ClientMsg : HumanoidNetworking.IMessage {
|
|
// public const byte Id = 0xA0; // 160
|
|
// public const byte length = 2;
|
|
// public byte networkId;
|
|
|
|
// public ClientMsg(byte networkId) {
|
|
// this.networkId = networkId;
|
|
// }
|
|
// public ClientMsg(byte[] data) : base(data) { }
|
|
|
|
// public override byte[] Serialize() {
|
|
// byte[] data = new byte[ClientMsg.length];
|
|
// data[0] = ClientMsg.Id;
|
|
// data[1] = this.networkId;
|
|
// return data;
|
|
// }
|
|
// public override void Deserialize(byte[] data) {
|
|
// base.Deserialize(data);
|
|
// uint ix = 0;
|
|
// networkId = data[ix++];
|
|
// }
|
|
//}
|
|
|
|
protected void SendClientMsg(HumanoidControl humanoid) {
|
|
if (debug <= HumanoidNetworking.DebugLevel.Debug)
|
|
Debug.Log("Send ClientMsg " + humanoid.nwId);
|
|
//ClientMsg clientMsg = new((byte)humanoid.nwId);
|
|
//SendMsg(clientMsg);
|
|
ClientMsg.Publish(client, (byte)humanoid.nwId);
|
|
}
|
|
#endregion Client
|
|
|
|
#region Pose
|
|
|
|
public virtual void UpdateHumanoidPose(HumanoidControl humanoid) {
|
|
if (debug <= HumanoidNetworking.DebugLevel.Debug)
|
|
Debug.Log("Send Pose Humanoid " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
|
|
|
|
SendBone(humanoid.hipsTarget.hips, true);
|
|
SendBone(humanoid.hipsTarget.spine);
|
|
SendBone(humanoid.hipsTarget.chest);
|
|
SendBone(humanoid.headTarget.neck);
|
|
SendBone(humanoid.headTarget.head);
|
|
|
|
SendBone(humanoid.leftHandTarget.upperArm);
|
|
SendBone(humanoid.leftHandTarget.forearm);
|
|
SendBone(humanoid.leftHandTarget.hand);
|
|
|
|
SendBone(humanoid.rightHandTarget.upperArm);
|
|
SendBone(humanoid.rightHandTarget.forearm);
|
|
SendBone(humanoid.rightHandTarget.hand);
|
|
|
|
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, bool isRoot = false) {
|
|
//RoboidBonePose bonePose = new(bone, isRoot);
|
|
//byte[] data = bonePose.Serialize();
|
|
//if (bonePose.bonePosition != null) {
|
|
// Debug.Log($"bone position {bone.bone.transform.position.x} {bone.bone.transform.position.y} {bone.bone.transform.position.z}");
|
|
// Debug.Log($"bone pos {bonePose.bonePosition.horizontal} {bonePose.bonePosition.vertical} {bonePose.bonePosition.distance}");
|
|
//}
|
|
//SendMsg(data);
|
|
|
|
if (isRoot) {
|
|
Quaternion orientation = bone.bone.transform.rotation;
|
|
Quat32 boneOrientation = new(orientation.x, orientation.y, orientation.z, orientation.w);
|
|
FromVector3(bone.bone.transform.position, out float distance, out float horizontal, out float vertical);
|
|
Spherical bonePosition = new(distance, horizontal, vertical);
|
|
PoseMsg.Send(client, (byte)bone.boneId, bonePosition, boneOrientation);
|
|
}
|
|
else {
|
|
Quaternion orientation = bone.bone.transform.localRotation;
|
|
Quat32 boneOrientation = new(orientation.x, orientation.y, orientation.z, orientation.w);
|
|
PoseMsg.Send(client, (byte)bone.boneId, null, boneOrientation);
|
|
}
|
|
}
|
|
|
|
#endregion Pose
|
|
|
|
//#region Messages
|
|
|
|
//#region NetworkId
|
|
|
|
void ProcessNetworkId(Client client, NetworkIdMsg msg) {
|
|
if (this.networkId == msg.networkId)
|
|
return;
|
|
|
|
this.networkId = msg.networkId;
|
|
client.networkId = msg.networkId;
|
|
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;
|
|
}
|
|
remoteHumanoid.nwId = msg.networkId;
|
|
|
|
SendThing(client, 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.hipsTarget.hips);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.hipsTarget.spine);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.hipsTarget.chest);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.headTarget.neck);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.headTarget.head);
|
|
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.leftHandTarget.upperArm);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.leftHandTarget.forearm);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.leftHandTarget.hand);
|
|
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.rightHandTarget.upperArm);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.rightHandTarget.forearm);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.rightHandTarget.hand);
|
|
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.upperLeg);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.lowerLeg);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.foot);
|
|
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.toes);
|
|
|
|
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
|
|
|
|
|
|
public void SendThing(Client client, HumanoidControl humanoid) {
|
|
if (debug <= HumanoidNetworking.DebugLevel.Debug)
|
|
Debug.Log("Send Thing " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
|
|
|
|
ThingMsg.Send(client, (byte)humanoid.nwId, 0, 1);
|
|
//ThingMsg thingMsg = new(0, 1);
|
|
//SendMsg(thingMsg);
|
|
//if (udpClient != null) {
|
|
// byte[] data = thingMsg.Serialize();
|
|
// udpClient.Send(data, data.Length, "127.0.0.1", nssPort);
|
|
//}
|
|
}
|
|
|
|
//#endregion Thing
|
|
|
|
//#region SubThing
|
|
|
|
public void SendSubThing(HumanoidControl humanoid, HumanoidTarget.TargetedBone bone) {
|
|
if (debug <= HumanoidNetworking.DebugLevel.Debug)
|
|
Debug.Log("Send SubThing " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
|
|
|
|
if (bone.parent != null)
|
|
ThingMsg.Send(client, (byte)bone.boneId, 0x00, (byte)bone.parent.boneId);
|
|
else
|
|
ThingMsg.Send(client, (byte)bone.boneId, 0x00, 0);
|
|
|
|
//SubThingMsg thingMsg;
|
|
//if (bone.parent != null)
|
|
// thingMsg = new((byte)bone.boneId, (byte)bone.parent.boneId, bone.bone.transform.position);
|
|
//else
|
|
// thingMsg = new((byte)bone.boneId, 0, 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 void SendName(HumanoidControl humanoid, byte thingId, string name) {
|
|
if (debug <= HumanoidNetworking.DebugLevel.Debug)
|
|
Debug.Log("Send Name " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
|
|
|
|
NameMsg.Send(client, thingId, name);
|
|
//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
|
|
|
|
public void SendModel(HumanoidControl humanoid, string url) {
|
|
if (debug <= HumanoidNetworking.DebugLevel.Debug)
|
|
Debug.Log("Send URL " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
|
|
|
|
ModelUrlMsg.Send(client, 0, url);
|
|
}
|
|
|
|
bool loaded = false;
|
|
protected async void ProcessModelURL(Client client, ModelUrlMsg msg) {
|
|
if (loaded)
|
|
return;
|
|
|
|
Debug.Log("Loading GLTF model from :" + msg.url);
|
|
GltfImport gltfImport = new GltfImport();
|
|
loaded = true;
|
|
// for .gltf...
|
|
bool success = await gltfImport.Load(msg.url);
|
|
if (success) {
|
|
Transform parentTransform = this.transform;
|
|
await gltfImport.InstantiateMainSceneAsync(parentTransform);
|
|
if (!success)
|
|
return;
|
|
//Camera camera = FindObjectOfType<Camera>(); // assuming just one camera per scene
|
|
//if (camera != null)
|
|
// camera.enabled = true;
|
|
Light[] lights = FindObjectsByType<Light>(FindObjectsSortMode.None);
|
|
foreach (Light light in lights)
|
|
light.intensity = 1; // light.intensity / 1000;
|
|
|
|
Renderer[] renderers = parentTransform.GetComponentsInChildren<Renderer>();
|
|
foreach (Renderer renderer in renderers)
|
|
renderer.gameObject.AddComponent<MeshCollider>();
|
|
}
|
|
}
|
|
|
|
|
|
//void ISiteServer.ProcessModelUrl(Client client, ModelUrlMsg msg) {
|
|
// int ix = msg.url.LastIndexOf(".");
|
|
// if (ix < 0)
|
|
// return;
|
|
|
|
// string extension = msg.url.Substring(msg.url.LastIndexOf("."));
|
|
// string extension3 = extension.Substring(0, 4);
|
|
// string extension4 = extension.Substring(0, 5);
|
|
// if (extension4 == ".gltf" || extension3 == ".glb") {
|
|
// ProcessGltfModel(msg);
|
|
// }
|
|
//}
|
|
|
|
#region GLTF
|
|
|
|
private bool loadingModel = false;
|
|
private Dictionary<string, GltfImport> gltfCache = new();
|
|
|
|
private async void ProcessGltfModel(ModelUrlMsg msg) {
|
|
if (gltfCache.TryGetValue(msg.url, out GltfImport gltfImport)) {
|
|
Debug.Log("Found buffered GLTF for: " + msg.url);
|
|
Transform parentTransform = await InstantiateGltf(gltfImport, msg.thingId, msg.scale);
|
|
Renderer[] renderers = parentTransform.GetComponentsInChildren<Renderer>();
|
|
foreach (Renderer renderer in renderers) {
|
|
MeshCollider c = renderer.gameObject.AddComponent<MeshCollider>();
|
|
c.convex = true;
|
|
}
|
|
|
|
}
|
|
else {
|
|
if (!loadingModel) {
|
|
loadingModel = true;
|
|
|
|
Debug.Log("Loading GLTF model from: " + msg.url);
|
|
gltfImport = new();
|
|
bool success = await gltfImport.Load(msg.url);
|
|
if (success) {
|
|
gltfCache.Add(msg.url, gltfImport);
|
|
loadingModel = false;
|
|
Transform parentTransform = await InstantiateGltf(gltfImport, msg.thingId, msg.scale);
|
|
ScanModelForThings(parentTransform);
|
|
}
|
|
else {
|
|
this.transform.localScale = Vector3.one * 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task<Transform> InstantiateGltf(GltfImport gltfImport, byte objectId, float scale) {
|
|
Debug.Log("Instantiate GLTF model");
|
|
Transform parentTransform = this.transform;
|
|
//Thing parentThing = allThings.Find(thing => thing.thingId == objectId);
|
|
//if (parentThing != null)
|
|
// parentTransform = parentThing.transform;
|
|
await gltfImport.InstantiateMainSceneAsync(parentTransform);
|
|
parentTransform.localScale = Vector3.one * scale;
|
|
return parentTransform;
|
|
}
|
|
|
|
private void ScanModelForThings(Transform parentTransform) {
|
|
//Debug.Log("scanning model for things.....");
|
|
//SkinnedMeshRenderer[] meshRenderers = parentTransform.GetComponentsInChildren<SkinnedMeshRenderer>();
|
|
//if (meshRenderers.Length > 0) {
|
|
// foreach (SkinnedMeshRenderer meshRenderer in meshRenderers) {
|
|
// if (meshRenderer.rootBone != null) {
|
|
// Debug.Log("Found a skinned mesh with bones");
|
|
// //string meshRendererName = meshRenderer.transform.name;
|
|
// //Thing meshRendererThing = allThings.Find(thing => thing.name == meshRendererName);
|
|
// //SkinnedMeshRenderer thingMeshRenderer = meshRendererThing.gameObject.AddComponent<SkinnedMeshRenderer>();
|
|
// //thingMeshRenderer.materials = meshRenderer.materials;
|
|
// //thingMeshRenderer.sharedMesh = meshRenderer.sharedMesh;
|
|
// //thingMeshRenderer.bones = GetSkinnedThings(meshRenderer);
|
|
|
|
// //ReplaceSkinnedBones(meshRenderer);
|
|
// //string rootBoneName = meshRenderer.rootBone.name;
|
|
// //Thing rootBoneThing = allThings.Find(thing => thing.name == rootBoneName);
|
|
// //if (rootBoneName != null)
|
|
// // meshRenderer.rootBone = rootBoneThing.transform;
|
|
// //else
|
|
// // Debug.LogWarning("Could not find the root bone thing");
|
|
// ScanForThings(meshRenderer.rootBone);
|
|
// //meshRenderer.rootBone = allThings.Find(thing => thing.thingId == 0).transform;
|
|
// break;
|
|
// }
|
|
// }
|
|
//}
|
|
//else {
|
|
// Renderer[] renderers = parentTransform.GetComponentsInChildren<Renderer>();
|
|
// foreach (Renderer renderer in renderers) {
|
|
// MeshCollider c = renderer.gameObject.AddComponent<MeshCollider>();
|
|
// c.convex = true;
|
|
// }
|
|
|
|
// ScanForThings(parentTransform);
|
|
//}
|
|
|
|
}
|
|
|
|
//private void ReplaceSkinnedBones(SkinnedMeshRenderer meshRenderer) {
|
|
// Transform[] bones = meshRenderer.bones;
|
|
// //foreach(Transform bone in bones) {
|
|
// for (int ix = 0; ix < bones.Length; ix++) {
|
|
// Thing boneThing = allThings.Find(thing => thing.name == bones[ix].name);
|
|
// if (boneThing != null) {
|
|
// Debug.Log($"Replace {bones[ix].name}");
|
|
// meshRenderer.bones[ix] = boneThing.transform;
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
//private Transform[] GetSkinnedThings(SkinnedMeshRenderer meshRenderer) {
|
|
// Transform[] bones = meshRenderer.bones;
|
|
// List<Transform> thingBones = new();
|
|
// //foreach(Transform bone in bones) {
|
|
// for (int ix = 0; ix < bones.Length; ix++) {
|
|
// Thing boneThing = allThings.Find(thing => thing.name == bones[ix].name);
|
|
// if (boneThing != null) {
|
|
// thingBones.Add(boneThing.transform);
|
|
// }
|
|
// }
|
|
// return thingBones.ToArray();
|
|
//}
|
|
|
|
//private void ScanForThings(Transform rootTransform) {
|
|
// Thing[] thingArray = allThings.ToArray();
|
|
|
|
// for (int thingIx = 0; thingIx < thingArray.Length; thingIx++) {
|
|
// Thing thing = thingArray[thingIx];
|
|
// //Debug.Log($"find {thing.name}");
|
|
// GameObject foundObj = FindThingByName(thing, rootTransform);
|
|
// if (foundObj != null) {
|
|
// Thing foundThing = foundObj.GetComponent<Thing>();
|
|
// if (foundObj != thing.gameObject) {
|
|
// if (foundThing == null) {
|
|
// allThings.Remove(thing);
|
|
// foundThing = thing.CopyTo(foundObj);
|
|
// allThings.Add(foundThing);
|
|
// }
|
|
// }
|
|
// if (thing.transform.childCount > foundObj.transform.childCount) {
|
|
// CopyChildren(thing, foundObj.transform);
|
|
// }
|
|
// //} else {
|
|
// // Debug.LogWarning($"Could not find thing {thing.name}");
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
//private GameObject FindThingByName(Thing thing, Transform rootTransform) {
|
|
// if (rootTransform == null || thing == null)
|
|
// return null;
|
|
|
|
// if (rootTransform.name == thing.name)
|
|
// return rootTransform.gameObject;
|
|
|
|
// for (int childIx = 0; childIx < rootTransform.childCount; childIx++) {
|
|
// Transform child = rootTransform.GetChild(childIx);
|
|
// GameObject foundObj = FindThingByName(thing, child);
|
|
// if (foundObj != null)
|
|
// return foundObj;
|
|
// }
|
|
// return null;
|
|
//}
|
|
|
|
//private void CopyChildren(Thing from, Transform to) {
|
|
// for (int childIx = 0; childIx < from.transform.childCount; childIx++) {
|
|
// Transform child = from.transform.GetChild(childIx);
|
|
// Debug.Log(child.name);
|
|
// bool found = false;
|
|
// foreach (Transform toChild in to) {
|
|
// if (child.name == toChild.name) {
|
|
// found = true;
|
|
// break;
|
|
// }
|
|
// }
|
|
// if (!found) {
|
|
// Debug.Log("...not found");
|
|
// Thing childThing = child.GetComponent<Thing>();
|
|
// if (childThing != null) {
|
|
// allThings.Remove(childThing);
|
|
// GameObject newChildObj = new GameObject(child.name);
|
|
// newChildObj.transform.SetParent(to.transform);
|
|
// newChildObj.transform.SetLocalPositionAndRotation(
|
|
// child.transform.localPosition, child.transform.localRotation);
|
|
// newChildObj.transform.localScale = Vector3.one;
|
|
// Thing newThing = childThing.CopyTo(newChildObj);
|
|
// allThings.Add(newThing);
|
|
// }
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
#endregion GLTF
|
|
|
|
|
|
//#endregion Model
|
|
|
|
//#region Pose
|
|
|
|
//[Serializable]
|
|
//public class RoboidBonePose : HumanoidNetworking.HumanoidPose {
|
|
// private readonly byte msgId = 0x10;
|
|
// readonly byte boneId;
|
|
// readonly Quat32 boneOrientation;
|
|
// public readonly Spherical16 bonePosition;
|
|
|
|
// public RoboidBonePose(HumanoidTarget.TargetedBone targetedBone, bool isRoot = false) {
|
|
// this.boneId = (byte)targetedBone.boneId;
|
|
// if (isRoot) {
|
|
// this.boneOrientation = new Quat32(targetedBone.bone.transform.rotation);
|
|
// this.bonePosition = Spherical16.FromVector3(targetedBone.bone.transform.position);
|
|
// }
|
|
// else
|
|
// this.boneOrientation = new Quat32(targetedBone.bone.transform.rotation);
|
|
// }
|
|
|
|
// public override byte[] Serialize() {
|
|
// byte[] data = new byte[11];
|
|
// data[0] = msgId;
|
|
// data[1] = boneId;
|
|
|
|
// if (bonePosition != null) {
|
|
// data[2] = 0x03; // Pose_position & Pose_orientation
|
|
// data[3] = bonePosition.horizontal;
|
|
// data[4] = bonePosition.vertical;
|
|
// ushort distanceRaw = bonePosition.distance.GetBinary();
|
|
// data[5] = (byte)(distanceRaw >> 8);
|
|
// data[6] = (byte)(distanceRaw & 0xFF);
|
|
// }
|
|
// else
|
|
// data[2] = 0x02; // Pose_orientation
|
|
|
|
|
|
// data[7] = boneOrientation.qx;
|
|
// data[8] = boneOrientation.qy;
|
|
// data[9] = boneOrientation.qz;
|
|
// data[10] = boneOrientation.qw;
|
|
// return data;
|
|
// }
|
|
//}
|
|
|
|
private static void FromVector3(Vector3 v, out float distance, out float horizontal, out float vertical) {
|
|
distance = v.magnitude;
|
|
if (distance == 0.0f) {
|
|
horizontal = 0;
|
|
vertical = 0;
|
|
}
|
|
else {
|
|
vertical = (Mathf.PI / 2 - Mathf.Acos(v.y / distance)) * Mathf.Rad2Deg;
|
|
horizontal = Mathf.Atan2(v.x, v.z) * Mathf.Rad2Deg;
|
|
}
|
|
}
|
|
|
|
//#endregion Pose
|
|
|
|
//#endregion Messages
|
|
|
|
#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);
|
|
//}
|
|
|
|
|
|
//protected void SendMsg(HumanoidNetworking.IMessage msg) {
|
|
// SendMsg(msg.Serialize());
|
|
//}
|
|
|
|
//protected void SendMsg(byte[] data) {
|
|
// if (udpClient == null)
|
|
// return;
|
|
|
|
// udpClient.Send(data, data.Length, "127.0.0.1", nssPort);
|
|
//}
|
|
|
|
#endregion Send
|
|
|
|
#region Receive
|
|
|
|
protected static float ReceiveAngle8(byte[] data, ref uint ix) {
|
|
float value = (data[ix++] * 180) / 128.0F;
|
|
return value;
|
|
}
|
|
|
|
protected static Vector3 ReceiveSpherical(byte[] data, ref uint ix) {
|
|
float horizontal = ReceiveAngle8(data, ref ix);
|
|
float vertical = ReceiveAngle8(data, ref ix);
|
|
float distance = ReceiveFloat16(data, ref ix);
|
|
Vector3 v = Quaternion.AngleAxis(horizontal, Vector3.up) * Quaternion.AngleAxis(vertical, Vector3.left) * (Vector3.forward * distance);
|
|
return v;
|
|
}
|
|
|
|
protected static float ReceiveFloat16(byte[] data, ref uint ix) {
|
|
ushort value = (ushort)(data[ix++] << 8 | data[ix++]);
|
|
float16 f16 = new float16();
|
|
f16.SetBinary(value);
|
|
float f = f16.toFloat();
|
|
return f;
|
|
}
|
|
|
|
#endregion Receive
|
|
}
|
|
}
|
|
#endif |