文章目录
- Zed-Unity插件代码注释——ZEDPointCloudManager.cs
- 引言
- 基础环境
- ZEDPointCloudManager.cs脚本介绍
- 代码(注释后)
Zed-Unity插件代码注释——ZEDPointCloudManager.cs
引言
由于项目的需求,需要在混合现实里面获得现实世界中一些物品的位置。ZED相机的双目相机提供了点云的数据,因此自己需要在unity中获得这些数据并进行实际需求的操作。
上个礼拜基本上把ZED-unity插件的原生接口代码通读了一遍,一方面是对整个SDK有了系统的了解,一方面是对C# 语言、Unity语言、这类产品的代码架构有了一定的了解。 而接下来正式转移到实际任务中的代码实践。
插件中提供了一个点云的显示示例,这篇文章先对这个示例的了解做一个简单的记录。代码注释等,下一篇再来考虑如何通过自己的代码来获得自己想要的点云的数据。
由于时间精力的限制,有一些可能觉得自己以后不怎么用的到的 但是现在又不懂的东西,我没有去分析它,但是在相应地方会指出说自己不懂,如果有人会的话,麻烦顺带解答一下。
基础环境
略(2020-09-01 20.46)
ZEDPointCloudManager.cs脚本介绍
- 脚本位置:
- 脚本功能:
这个脚本是一个mono的子类,在里面有update()、Aware()等unity的函数。 是一个数据显示的示例脚本,是教开发者如何在unity中实时显示zed相机点云的。
-脚本使用:
这个脚本相当于一个脚本组件,需要放置在unity场景中的GameObject上才能运行,脚本对宿主(我自己把组件挂在的对象称为宿主)没有要求。
脚本要求另外一个脚本组件“ZEDManager.cs”也挂在某个宿主身上。 - 代码结构:
该脚本比较短,也就388行。内容比较少,这边就不详细说了。直接看代码里面的注释吧。
代码(注释后)
//======= Copyright (c) Stereolabs Corporation, All rights reserved. ===============
using UnityEngine;
/*
* Editor:Lance
* 注释时间:初次 2020-09-01 17.18
*/
/// <summary>
/// Displays the point cloud of the real world in front of the camera.
/// Can be attached to any GameObject in a scene, but requires a ZEDManager component to exist somewhere.
/// 镜头前显示现实世界的点云。
/// 可以附加到场景中的任何GameObject,但需要ZEDManager组件存在于某个地方。
/// </summary>
public class ZEDPointCloudManager : MonoBehaviour
{
/// <summary>
/// Set to a camera if you do not want that camera to see the point cloud.
/// 如果您不希望该摄像机看到点云,则设置为摄像机。
/// 不希望这个相机看到点云
/// Editor Lance:这个是什么意思呢,是说设置一个新的虚拟相机,这个相机看不到点云对象?
/// </summary>
[Tooltip("Set to a camera if you do not want that camera to see the point cloud. ")]
public Camera hiddenObjectFromCamera;
/// <summary>
/// Instance of the ZEDManager interface
/// ZEDManager界面的实例,后面应该是要将外部的zedmanager赋值给下面这个变量才对
/// </summary>
public ZEDManager zedManager = null;
/// <summary>
/// Material used to display the point cloud. Usually Mat_ZED_PointCloud.
/// 用于显示点云的材质。通常为Mat_ZED_PointCloud。
/// </summary>
public Material mat;
/// <summary>
/// Number of points displayed. Usually equal to the width * height of the ZED's resolution (eg. 1280 * 720).
/// 显示的点数。通常等于ZED分辨率的宽度*高度(例如1280 * 720)。
/// </summary>
private int numberPoints = 0;
/// <summary>
/// zed Camera controller by zedManager
/// zedManager的zed相机控制器
/// </summary>
private sl.ZEDCamera zed = null;
/// <summary>
/// Texture that holds the 3D position of the points.
/// 保持点的3D位置的纹理。
/// </summary>
private Texture2D XYZTexture; //Editor Lance:点云纹理,纹理数据与zed的点云数据格式不同,不是一个矩阵
/// <summary>
/// Texture that holds the colors of each point.
/// 保留每个点的颜色的纹理
/// </summary>
private Texture2D colorTexture; //Editor Lance:彩色图像的纹理
/// <summary>
/// Temporary copy/buffer of the XYZTexture to stop the point cloud in a defined moment.
/// XYZTexture的临时副本/缓冲区,用于在定义的时刻停止点云。
/// </summary>
private RenderTexture XYZTextureCopy = null; //Editor Lance:渲染的纹理对象是什么东西,就是一个临时的纹理变量吧
/// <summary>
/// Temporary copy/buffer of the ColorTexture to stop the point cloud in a defined moment.
/// ColorTexture的临时副本/缓冲区,用于在定义的瞬间停止点云。
/// </summary>
private RenderTexture ColorTextureCopy = null;
/// <summary>
/// Cached property index of _Position shader property, so we only look it up once. Do not use.
/// _Position shader属性的缓存属性索引,因此我们只查找一次。不使用。
/// </summary>
/// Editor Lance: int?用法
private static int? _positionid;
/// <summary>
/// Returns the property index of the _Position property, and looks it up if it hasn't been looked up yet.
/// 返回_Position属性的属性索引,如果尚未查找,则查找它。
/// </summary>
private static int positionID
{
get
{
if (_positionid == null)
{
_positionid = Shader.PropertyToID("_Position"); //
}
return (int) _positionid;
}
}
/// <summary>
/// Cached property index of the _ColorTex shader property, so we only look it up once. Use colorTexID instead.
/// _ColorTex着色器属性的缓存属性索引,因此我们只查找一次。请改用colorTexID。
/// </summary>
private static int? _colortexid;
/// <summary>
/// Returns the property index of the _ColorTex property, which is the RGB color texture from the ZED.
/// 返回_ColorTex属性的属性索引,该属性索引是ZED中的RGB颜色纹理。
/// </summary>
private static int colorTexID
{
get
{
if (_colortexid == null)
{
_colortexid = Shader.PropertyToID("_ColorTex");
}
return (int) _colortexid;
}
}
/// <summary>
/// Cached property index of _XYZTex shader property, so we only look it up once. Use xyzTexID instead.
/// _XYZTex着色器属性的缓存属性索引,因此我们只查找一次。请改用xyzTexID。
/// </summary>
private static int? _xyztexid;
/// <summary>
/// Returns the property index of the _XYZTex property, which is the XYZ position of each pixel relative to the ZED.
/// 返回_XYZTex属性的属性索引,该索引是每个像素相对于ZED的XYZ位置。
/// </summary>
private static int xyzTexID
{
get
{
if (_xyztexid == null)
{
_xyztexid = Shader.PropertyToID("_XYZTex");
}
return (int) _xyztexid;
}
}
/// <summary>
/// Whether the point cloud should be visible or not.
/// 点云是否应该可见。
/// </summary>
[Tooltip("Whether the point cloud should be visible or not.点云是否应该可见。 ")]
public bool display = true;
/// <summary>
/// Whether to update the point cloud.
/// If false, the point cloud will display the content of the temp textures from the last update.
/// 是否更新点云。 如果为false,则点云将显示上一次更新的临时纹理的内容。
/// </summary>
[Tooltip(
"Whether to update the point cloud. If false, the point cloud will display the content of the temp textures from the last update. " +
"是否更新点云。 如果为false,则点云将显示上一次更新的临时纹理的内容。")]
public bool update = true;
/// <summary>
/// Flag to check if the update has changed state.
/// 标记以检查更新是否已更改状态。
/// </summary>
private bool previousUpdate = true;
void Start()
{
if (zedManager == null) //如果还没有实例化
{
zedManager = FindObjectOfType<ZEDManager>(); //找到ZEDManager组件
if (ZEDManager.GetInstances().Count > 1 //如果这个组件的实例化不只一个,我的情况一般只有一个
) //We chose a ZED arbitrarily, but there are multiple cams present. Warn the user.
我们任意选择一个ZED,但是有多个相机存在。所以需要警告用户。
{
Debug.Log("Warning: " + gameObject.name +
"'s zedManager was not specified, so the first available ZEDManager instance was " +
"assigned. However, there are multiple ZEDManager's in the scene. It's recommended to specify which ZEDManager you want to " +
"use to display a point cloud.");
}
}
if (zedManager != null) //实例化后的
zed = zedManager.zedCamera; //相机设备赋值
}
// Update is called once per frame
void Update()
{
//Don't do anything unless the ZED has been initialized.
// 除非ZED已初始化,否则请勿执行任何操作。
if (zed.IsCameraReady)
{
if (numberPoints == 0) //这个判断里面的内容只执行一次
{
//Create the textures. These will be updated automatically by the ZED.
//创建纹理。这些将由ZED自动更新。
//We'll copy them each frame into XYZTextureCopy and ColorTextureCopy, which will be the ones actually displayed.
//我们将每帧将它们复制到XYZTextureCopy和ColorTextureCopy中,它们将是显示的。
XYZTexture = zed.CreateTextureMeasureType(sl.MEASURE.XYZ);
colorTexture = zed.CreateTextureImageType(sl.VIEW.LEFT);
numberPoints = zed.ImageWidth * zed.ImageHeight; //点云的数目赋值
//Load and set the material properties.
//加载并设置材料属性。
if (mat == null)
{
mat = new Material(
Resources.Load("Materials/PointCloud/Mat_ZED_PointCloud") as Material); //插件包中加载点云的材质
}
if (mat != null)
{
//mat.SetTexture("_XYZTex", XYZTexture);
mat.SetTexture(xyzTexID, XYZTexture); // 把点云的纹理图设置到材质里面
//mat.SetTexture("_ColorTex", colorTexture);
mat.SetTexture(colorTexID, colorTexture); //把图像的彩色纹理图设置到材质里面
}
}
//If stop updated, create new render texture and fill them with the textures from the ZED.
//如果停止更新,请创建新的渲染纹理,并使用ZED中的纹理填充它们。
// These textures will be displayed as they are not updated
//这些纹理将被显示,因为它们没有更新
if (!update && previousUpdate != update) //Editor Lance:这个判断好奇怪,好像当previousUpdate为true的时候一定能通过
// Editor Lance:这边的意思是说 当update为false的时候,这个函数还是被执行了一帧,但是第二帧的时候就不能执行了
{
if (XYZTextureCopy == null) //如果没有复制过之前的点云纹理
{
XYZTextureCopy = new RenderTexture(XYZTexture.width, XYZTexture.height, 0,
RenderTextureFormat.ARGBFloat); //实例化临时纹理,浮点类型
}
if (ColorTextureCopy == null) // 如果没有临时的彩色纹理
{
ColorTextureCopy = new RenderTexture(colorTexture.width, colorTexture.height, 0,
RenderTextureFormat.ARGB32); //实例化临时纹理,字符串类型
}
//Copy the new textures into the buffers.
//将新纹理复制到缓冲区中。
Graphics.Blit(XYZTexture, XYZTextureCopy); //Unity的函数 之后再了解
Graphics.Blit(colorTexture, ColorTextureCopy);
if (mat != null) //如果材质已经生成
{
//mat.SetTexture("_XYZTex", XYZTextureCopy);
mat.SetTexture(xyzTexID, XYZTextureCopy); // 应用临时纹理
//mat.SetTexture("_ColorTex", ColorTextureCopy);
mat.SetTexture(colorTexID, ColorTextureCopy); // 应用临时纹理
}
}
//Send the textures to the material/shader.
//将纹理发送到材质/着色器。
if (update && previousUpdate != update && mat != null
) // 暂停后又重新开始的话能够进入,但是当update为false的时候是不进入的。当mat没有初始化的时候也是不能进入的。
{
//mat.SetTexture("_XYZTex", XYZTexture);
mat.SetTexture(xyzTexID, XYZTexture);
//mat.SetTexture("_ColorTex", colorTexture);
mat.SetTexture(colorTexID, colorTexture);
}
previousUpdate = update;
}
}
void OnApplicationQuit() //退出的时候释放内存
{
//Free up memory.
mat = null;
if (XYZTextureCopy != null)
{
XYZTextureCopy.Release(); //释放临时纹理的内存
}
if (ColorTextureCopy != null)
{
ColorTextureCopy.Release(); //释放临时纹理的内存
}
}
void OnRenderObject()
{
if (mat != null) //如果材质已经实例化
{
if (hiddenObjectFromCamera == Camera.current) return; //如果我就不想看点云的话
if (!display) return; //Don't draw anything if the user doesn't want to. 如果用户不想画任何东西。
//mat.SetMatrix("_Position", transform.localToWorldMatrix);
mat.SetMatrix(positionID, transform.localToWorldMatrix); //从局部转换到世界坐标系中,
mat.SetPass(0); //这个是啥
#if UNITY_2019_1_OR_NEWER
Graphics.DrawProceduralNow(MeshTopology.Points, 1, numberPoints);
#else
Graphics.DrawProcedural(MeshTopology.Points, 1, numberPoints);
#endif
}
}
}