You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
4.3 KiB

using System;
using UnityEngine;
using Intel.RealSense;
using UnityEngine.Rendering;
using UnityEngine.Assertions;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class RsPointCloudRenderer : MonoBehaviour
{
public RsFrameProvider Source;
private Mesh mesh;
private Texture2D uvmap;
[NonSerialized]
private Vector3[] vertices;
FrameQueue q;
void Start()
{
Source.OnStart += OnStartStreaming;
Source.OnStop += Dispose;
}
private void OnStartStreaming(PipelineProfile obj)
{
q = new FrameQueue(1);
using (var depth = obj.Streams.FirstOrDefault(s => s.Stream == Stream.Depth && s.Format == Format.Z16).As<VideoStreamProfile>())
ResetMesh(depth.Width, depth.Height);
Source.OnNewSample += OnNewSample;
}
private void ResetMesh(int width, int height)
{
Assert.IsTrue(SystemInfo.SupportsTextureFormat(TextureFormat.RGFloat));
uvmap = new Texture2D(width, height, TextureFormat.RGFloat, false, true)
{
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Point,
};
GetComponent<MeshRenderer>().sharedMaterial.SetTexture("_UVMap", uvmap);
if (mesh != null)
mesh.Clear();
else
mesh = new Mesh()
{
indexFormat = IndexFormat.UInt32,
};
vertices = new Vector3[width * height];
var indices = new int[vertices.Length];
for (int i = 0; i < vertices.Length; i++)
indices[i] = i;
mesh.MarkDynamic();
mesh.vertices = vertices;
var uvs = new Vector2[width * height];
Array.Clear(uvs, 0, uvs.Length);
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
uvs[i + j * width].x = i / (float)width;
uvs[i + j * width].y = j / (float)height;
}
}
mesh.uv = uvs;
mesh.SetIndices(indices, MeshTopology.Points, 0, false);
mesh.bounds = new Bounds(Vector3.zero, Vector3.one * 10f);
GetComponent<MeshFilter>().sharedMesh = mesh;
}
void OnDestroy()
{
if (q != null)
{
q.Dispose();
q = null;
}
if (mesh != null)
Destroy(null);
}
private void Dispose()
{
Source.OnNewSample -= OnNewSample;
if (q != null)
{
q.Dispose();
q = null;
}
}
private void OnNewSample(Frame frame)
{
if (q == null)
return;
try
{
if (frame.IsComposite)
{
using (var fs = frame.As<FrameSet>())
using (var points = fs.FirstOrDefault<Points>(Stream.Depth, Format.Xyz32f))
{
if (points != null)
{
q.Enqueue(points);
}
}
return;
}
if (frame.Is(Extension.Points))
{
q.Enqueue(frame);
}
}
catch (Exception e)
{
Debug.LogException(e);
}
}
protected void LateUpdate()
{
if (q != null)
{
Points points;
if (q.PollForFrame<Points>(out points))
using (points)
{
if (points.Count != mesh.vertexCount)
{
using (var p = points.GetProfile<VideoStreamProfile>())
ResetMesh(p.Width, p.Height);
}
if (points.TextureData != IntPtr.Zero)
{
uvmap.LoadRawTextureData(points.TextureData, points.Count * sizeof(float) * 2);
uvmap.Apply();
}
if (points.VertexData != IntPtr.Zero)
{
points.CopyVertices(vertices);
mesh.vertices = vertices;
mesh.UploadMeshData(false);
}
}
}
}
}