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