Newer
Older
HoloAnatomy / Assets / HoloToolkit / SpatialMapping / Scripts / RemoteMapping / RemoteMeshTarget.cs
SURFACEBOOK2\jackwynne on 25 May 2018 5 KB v1
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License. See LICENSE in the project root for license information.
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. #if UNITY_EDITOR || UNITY_STANDALONE_WIN
  8. using System.Net;
  9. using System.Net.Sockets;
  10. #endif
  11. using UnityEngine;
  12.  
  13. namespace HoloToolkit.Unity.SpatialMapping
  14. {
  15. /// <summary>
  16. /// RemoteMeshTarget will listen for meshes being sent from a remote system (HoloLens).
  17. /// It is intended to run in the Unity Editor with exactly one
  18. /// HoloLens device sending data.
  19. /// </summary>
  20. public class RemoteMeshTarget : SpatialMappingSource
  21. {
  22. [Tooltip("The IPv4 Address of the machine running the Unity editor.")]
  23. public string ServerIP;
  24.  
  25. [Tooltip("The connection port on the machine to use.")]
  26. public int ConnectionPort = 11000;
  27.  
  28. #if UNITY_EDITOR || UNITY_STANDALONE_WIN
  29. /// <summary>
  30. /// Listens for network connections over TCP.
  31. /// </summary>
  32. private TcpListener networkListener;
  33.  
  34. /// <summary>
  35. /// Keeps client information when a connection happens.
  36. /// </summary>
  37. private TcpClient networkClient;
  38.  
  39. /// <summary>
  40. /// Tracks if a client is connected.
  41. /// </summary>
  42. private bool clientConnected;
  43.  
  44. // Use this for initialization.
  45. private void Start()
  46. {
  47. // Setup the network listener.
  48. IPAddress localAddr = IPAddress.Parse(ServerIP.Trim());
  49. networkListener = new TcpListener(localAddr, ConnectionPort);
  50. networkListener.Start();
  51.  
  52. // Request the network listener to wait for connections asynchronously.
  53. AsyncCallback callback = OnClientConnect;
  54. networkListener.BeginAcceptTcpClient(callback, this);
  55. }
  56.  
  57. // Update is called once per frame.
  58. private void Update()
  59. {
  60. // If we have a connected client, presumably the client wants to send some meshes.
  61. if (clientConnected)
  62. {
  63. // Get the clients stream.
  64. NetworkStream stream = networkClient.GetStream();
  65.  
  66. // Make sure there is data in the stream.
  67. if (stream.DataAvailable)
  68. {
  69. // The first 4 bytes will be the size of the data containing the mesh(es).
  70. int datasize = ReadInt(stream);
  71.  
  72. // Allocate a buffer to hold the data.
  73. byte[] dataBuffer = new byte[datasize];
  74.  
  75. // Read the data.
  76. // The data can come in chunks.
  77. int readsize = 0;
  78.  
  79. while (readsize != datasize)
  80. {
  81. readsize += stream.Read(dataBuffer, readsize, datasize - readsize);
  82. }
  83.  
  84. if (readsize != datasize)
  85. {
  86. Debug.Log("reading mesh failed: " + readsize + " != " + datasize);
  87. }
  88.  
  89. // Pass the data to the mesh serializer.
  90. List<Mesh> meshes = new List<Mesh>(SimpleMeshSerializer.Deserialize(dataBuffer));
  91.  
  92. if (meshes.Count > 0)
  93. {
  94. // Use the network-based mapping source to receive meshes in the Unity editor.
  95. SpatialMappingManager.Instance.SetSpatialMappingSource(this);
  96. }
  97.  
  98. // For each mesh, create a GameObject to render it.
  99. for (int index = 0; index < meshes.Count; index++)
  100. {
  101. int meshID = SurfaceObjects.Count;
  102.  
  103. SurfaceObject surface = CreateSurfaceObject(
  104. mesh: meshes[index],
  105. objectName: "Beamed-" + meshID,
  106. parentObject: transform,
  107. meshID: meshID
  108. );
  109.  
  110. surface.Object.transform.parent = SpatialMappingManager.Instance.transform;
  111.  
  112. AddSurfaceObject(surface);
  113. }
  114.  
  115. // Finally disconnect.
  116. clientConnected = false;
  117. networkClient.Close();
  118.  
  119. // And wait for the next connection.
  120. AsyncCallback callback = OnClientConnect;
  121. networkListener.BeginAcceptTcpClient(callback, this);
  122. }
  123. }
  124. }
  125.  
  126. /// <summary>
  127. /// Reads an int from the next 4 bytes of the supplied stream.
  128. /// </summary>
  129. /// <param name="stream">The stream to read the bytes from.</param>
  130. /// <returns>An integer representing the bytes.</returns>
  131. private int ReadInt(Stream stream)
  132. {
  133. // The bytes arrive in the wrong order, so swap them.
  134. byte[] bytes = new byte[4];
  135. stream.Read(bytes, 0, 4);
  136. byte t = bytes[0];
  137. bytes[0] = bytes[3];
  138. bytes[3] = t;
  139.  
  140. t = bytes[1];
  141. bytes[1] = bytes[2];
  142. bytes[2] = t;
  143.  
  144. // Then bitconverter can read the int32.
  145. return BitConverter.ToInt32(bytes, 0);
  146. }
  147.  
  148. /// <summary>
  149. /// Called when a client connects.
  150. /// </summary>
  151. /// <param name="result">The result of the connection.</param>
  152. private void OnClientConnect(IAsyncResult result)
  153. {
  154. if (result.IsCompleted)
  155. {
  156. networkClient = networkListener.EndAcceptTcpClient(result);
  157. if (networkClient != null)
  158. {
  159. Debug.Log("Connected");
  160. clientConnected = true;
  161. }
  162. }
  163. }
  164. #endif
  165. }
  166. }