Zed-Unity插件代码注释——ZEDCamera.CS

@[toc

Zed-Unity插件代码注释——ZEDCamera.cs

引言

Zed-Unity插件提供了在Unity中访问ZED相机SDK的工具,除了提供了SDK的接口外,插件里面还有一些很典型的demo,供开发者参考。

不得不说ZED的文档写的确实很用心, 每个脚本3000多行,但是里面一半以上是注释说明,由于是英文的,看的时候效率较低。
考虑到自己刚刚入门Unity和C#。 有很多知识点需要学,同时也因为现在项目需要的代码量越来越大,一直没有学过程序设计方面的东西,所以打算通读一下这个sdk的代码,顺便学习一些框架类的皮毛。
在通读的代码的过程,也会把里面的注释翻译成中文方便理解,所以就把中文的内容顺手添加到脚本里面去,方便后面自己回看,和后面的人学习。

基础环境

操作系统: Win10 专业版(不是必须的配置,只是习惯性统一写出来)
C# 版本:8.0
Unity版本:2019
Rider版本:2020
ZED型号:ZED-Mini
SDK版本:3.1
ZED-Unity插件版本:3.1

ZedCamera.cs脚本介绍

  • 脚本位置:
    Zed-Unity插件代码注释——ZEDCamera.CS_第1张图片

  • 脚本的功能:
    这个脚本是插件里面较为底层的脚本,定义了一个命名空间sl,然后定义了一个ZEDCamera的基础类,这个类没有继承Unity的Mono,所以里面没有类似Unity脚本中的 update()、aware()这类型的函数。因此这个脚本在unity中主要是被其他的脚本引用的。在插件里面主要是在ZEDManager.cs中被调用。
    这个脚本里面通过[DllImport]引入了SDK的动态链接库(.dll)。并定义了一些在Unity中使用的函数接口,这些函数内部的内容多为调用外部函数(.dll)以实现,只是方便Unity中识别使用。

  • 命名空间:sl (在其他脚本中调用这个脚本的时候需要用)

  • 类名称:ZEDCamera

  • 代码结构:
    0~365行:定义了所需要的大部分变量,包括私有和公开的。私有类型的名命规则
    365~792行:都是[DllImport]载入动态链接库的代码,以及在C#中对载入函数入口的声明,这部分代码可以不看,基本上是固定的。
    792~3040行:定义了一些函数,基本上里面都是调用了前面载入的外部函数。 包括相机参数设定、相机追踪功能、图像数据注册、深度数据注册等等的功能。 这些函数在ZEDManager.cs被调用。更细节的就不在这边展开了,直接从代码里面看吧。

ZedCamera.cs代码(注释后)

//======= Copyright (c) Stereolabs Corporation, All rights reserved. ===============

using UnityEngine;
using System.Collections.Generic;
using System;
using System.Runtime.InteropServices;
using System.Reflection;

namespace sl //定义命名空间
{
    /// 
    /// Main interface between Unity and the ZED SDK. Primarily consists of extern calls to the ZED SDK wrapper .dll and
    /// low-level logic to process data sent to/received from it.
    /// Unity和ZED SDK之间的主要接口。主要包括对ZED SDK包装程序 .dll和
    /// 低级逻辑的外部调用,以处理发送给它的数据或从中接收的数据
    /// 
    /// The ZEDManager component creates a ZEDCamera instance in Awake() and handles all initialization.
    /// Most ZED functionality can be handled simply in Unity via ZEDManager or other high-level manager components
    /// (ZEDSpatialMappingManager, ZEDPlaneDetectionManager, etc.)
    /// Textures created by ZEDCamera by CreateTextureImageType() and CreateTextureMeasureType()
    /// are updated automatically by the wrapper whenever a new frame is available. They represent a specific kind of
    /// output, like left RGB image, or depth relative to the right sensor. As such, you never need more than one texture
    /// of each kind, since it can simply be reused by all scripts that need it. Therefore, textures created in ZEDCamera
    /// are indexed by their type (Image or Measure) and then by the options of each type. If a script needs a certain kind
    /// of output, ZEDCamera will make a new one if it doesn't exist, but refer to the existing one otherwise.
    /// ZEDManager组件在Awake()中创建一个ZEDCamera实例并处理所有初始化。
    /// 大多数ZED功能可以通过ZEDManager或其他高级管理器组件简单地在Unity中处理
    /// ((ZEDSpatialMappingManager,ZEDPlaneDetectionManager等)
    /// ZEDCamera通过CreateTextureImageType()和CreateTextureMeasureType()创建的纹理
    /// 只要有新帧,包装器就会自动更新。它们代表一种特定的输出,例如左RGB图像或相对于右传感器的深度。这样,您只需要一个texture就可以
    /// 因为它可以被所有需要它的脚本简单地重用。因此,在ZEDCamera中创建的纹理
    /// 由其类型(图像或度量)索引,然后由每种类型的选项索引。如果脚本需要某种输出
    /// 则ZEDCamera创建一个新的,或者引用现有的输出。
    public class ZEDCamera
    {
        /// 
        /// Type of textures requested.
        /// 定义几个纹理的类型
        /// 
        public enum TYPE_VIEW //定义一个枚举类型,
        {
            /// 枚举类型的相关知识 https://www.cnblogs.com/liujianshe1990-/p/10247930.html
            /// 
            /// Image-type texture. Human-viewable but loses measurement accuracy.
            /// 图像类型的纹理。肉眼可见但会失去测量精度。
            /// Lance:指的应该就是采用RGB图像显示把
            /// 
            RETRIEVE_IMAGE,

            /// 
            /// Measure-type texture. Preserves measurement accuracy but isn't human-viewable.
            /// 测量型纹理。保持测量精度,但人眼看不到。
            /// Lance:指的应该是计算过深度的模式
            /// 
            RETRIEVE_MEASURE
        }

        /// 
        /// Information for a requested texture. Stored in the texturesRequested list so DestroyTexture()
        /// can be called with the correct arguments in DestroyAllTexture().
        /// 所需纹理的信息。存储在texturesRequested列表中,
        /// 因此可以在DestroyAllTexture()中使用正确的参数调用DestroyTexture()。
        /// 
        private struct TextureRequested //定义一个结构体
        {
            /// 
            /// Texture type - 'image' or 'measure.' Assigned using ZEDCamera.TYPE_VIEW.
            /// 纹理类型-“image”或“measure”。使用ZEDCamera.TYPE_VIEW分配。
            /// Lance:texture、image、measure不知道怎么翻译才合适
            /// 
            public int type;

            /// 
            /// View mode (left/right eye, depth, etc.) Assigned using ZEDCommon.VIEW.
            /// 观察的模式(左/右眼,深度等).在ZEDCommon.VIEW中被使用。
            /// 
            public int option;
        };

        #region 相机成员,这边定义大量的属性
        /********* Camera members ********/
        /// 
        /// DLL name, used for extern calls to the wrapper.
        /// DLL名称,用于外部调用包装程序。
        /// 
        const string nameDll = sl.ZEDCommon.NameDLL;

        /// 
        /// List of all created textures, representing SDK output. Indexed by ints corresponding to its ZEDCamera.TYPE_VIEW
        /// and its ZEDCommon.VIEW as you can't have more than one texture for each combination (nor would it be useful to).
        /// 所有创建的纹理的列表,表示SDK输出。由与它的ZEDCamera.TYPE_VIEW
        /// 和它的ZEDCommon.VIEW对应的int进行索引,因为每种组合都不能有多个纹理(也没有用)
        /// Lance:不是很明白这边的东西
        /// 
        private Dictionary<int, Dictionary<int, Texture2D>> textures; // 注册一个纹理的列表,是两个嵌套字典,最里面的元素内容是2D的纹理

        /// 
        /// List of all requested textures. Used for destroying all textures when the camera closes.
        /// 所有请求的纹理的列表。关闭相机时用于破坏所有纹理。
        /// 
        private List<TextureRequested> texturesRequested;

        /// 
        /// Width of the textures in pixels. Corresponds to the ZED's current resolution setting.
        /// 纹理的宽度(以像素为单位)。对应于ZED的当前分辨率设置。
        /// 
        private int imageWidth;

        /// 
        /// Width of the images returned by the ZED in pixels. Corresponds to the ZED's current resolution setting.
        /// ZED返回的图像的宽度(以像素为单位)。对应于ZED的当前分辨率设置。
        /// Lance:  数据要在Unity中显示,就需要放到相应的texture上,因此图像的分辨率相当于unity中相应的texture的宽度
        /// 
        public int ImageWidth
        {
            get { return imageWidth; }
        }

        /// 
        /// Height of the textures in pixels. Corresponds to the ZED's current resolution setting.
        /// 纹理的高度(以像素为单位)。对应于ZED的当前分辨率设置。
        /// 
        private int imageHeight;

        /// 
        /// Height of the images returned by the ZED in pixels. Corresponds to the ZED's current resolution setting.
        /// ZED返回的图像的高度(以像素为单位)。对应于ZED的当前分辨率设置。
        /// 
        public int ImageHeight
        {
            get { return imageHeight; }
        }

        /// 
        /// Projection matrix corresponding to the ZED's camera traits. Useful for lining up virtual cameras with the ZED image.
        /// 与ZED的相机特征相对应的投影矩阵。对于将虚拟相机与ZED图像对齐非常有用。
        /// 
        private Matrix4x4 projection = new Matrix4x4();

        /// 
        /// Projection matrix corresponding to the ZED's camera traits. Useful for lining up virtual cameras with the ZED image.
        /// 与ZED的相机特征相对应的投影矩阵。对于将虚拟相机与ZED图像对齐非常有用。
        /// 
        public Matrix4x4 Projection //定义一个私有的变量再定义一个共有的变量,这是为了防止外部类修改这个变量,引起不稳定
        {
            get { return projection; }
        }


        /// 
        /// True if the ZED SDK is installed.
        /// 如果已安装ZED SDK,则为True。
        /// 
        private static bool pluginIsReady = true;

        /// 
        /// Mutex for the image acquisition thread.
        /// 用于图像获取线程的Mutex。
        /// Lance:这是一个object类,可以接收各种类型的对象
        /// 
        public object grabLock = new object();

        /// 
        /// Current ZED resolution setting. Set at initialization.
        /// 当前的ZED分辨率设置。在初始化时设置。
        /// 
        private RESOLUTION currentResolution;

        /// 
        /// Callback for c++ debugging. Should not be used in C#.
        /// 用于c ++调试的回调。不应在C#中使用。
        /// 
        private delegate void DebugCallback(string message);

        /// 
        /// Desired FPS from the ZED camera. This is the maximum FPS for the ZED's current
        /// resolution unless a lower setting was specified in Init().
        /// Maximum values are bound by the ZED's output, not system performance.
        /// ZED相机所需的FPS。
        /// 除非在Init()中指定了较低的设置,否则这是ZED当前分辨率的最大FPS。
        /// 最大值受ZED输出限制,而不是系统性能限制。
        /// 
        private uint fpsMax = 60; //Defaults to HD720 resolution's output.

        /// 
        /// Desired FPS from the ZED camera. This is the maximum FPS for the ZED's current
        /// resolution unless a lower setting was specified in Init().
        /// Maximum values are bound by the ZED's output, not system performance.
        /// ZED相机所需的FPS。除非在Init()中指定了较低的设置,否则这是ZED当前分辨率的最大FPS。
        /// 最大值受ZED输出限制,而不是系统性能限制。
        /// 
        public float GetRequestedCameraFPS() //获得最大采集帧率
        {
            return fpsMax;
        }

        /// 
        /// Holds camera settings like brightness/contrast, gain/exposure, etc.
        /// 保持相机设置,例如亮度/对比度,增益/曝光等。
        /// 
        private ZEDCameraSettings cameraSettingsManager = new ZEDCameraSettings();

        /// 
        /// Camera's stereo baseline (distance between the cameras). Extracted from calibration files.
        /// 相机的立体基线(相机之间的距离)。从校准文件中提取。
        /// 
        private float baseline = 0.0f; //可以从这边获得基线的值,可能把这个API用于hololens的时候可以通过修改这个来适应HoloLens的双目图像

        /// 
        /// Camera's stereo baseline (distance between the cameras). Extracted from calibration files.
        /// 相机的立体基线(相机之间的距离)。从校准文件中提取。
        /// 
        public float Baseline //获得相机的基线
        {
            get { return baseline; }
        }

        /// 
        /// ZED's current horizontal field of view in degrees.
        /// ZED当前的水平视场,以度为单位。
        /// 
        private float fov_H = 0.0f;

        /// 
        /// ZED's current vertical field of view in degrees.
        /// ZED当前的垂直视场,以度为单位。
        /// 
        private float fov_V = 0.0f;

        /// 
        /// ZED's current horizontal field of view in degrees.
        /// ZED当前的水平视场,以度为单位。
        /// 
        public float HorizontalFieldOfView
        {
            get { return fov_H; }
        }

        /// 
        /// ZED's current vertical field of view in degrees.
        /// ZED当前的垂直视场,以度为单位。
        /// 
        public float VerticalFieldOfView
        {
            get { return fov_V; }
        }

        /// 
        /// Stereo parameters for current ZED camera prior to rectification (distorted).
        /// 校正前当前ZED摄像机的双目视觉的参数(失真)。
        /// Lance:这边应该是矫正畸变前的参数
        /// 
        private CalibrationParameters calibrationParametersRaw; //相机畸变矫正参数

        /// 
        /// Stereo parameters for current ZED camera prior to rectification (distorted).
        /// 校正前当前ZED摄像机的stereo参数(失真)。
        /// 
        public CalibrationParameters CalibrationParametersRaw
        {
            get { return calibrationParametersRaw; }
        }

        /// 
        /// Stereo parameters for current ZED camera after rectification (undistorted).
        /// 校正后当前ZED摄像机的stereo参数(未失真)。
        /// Lance:矫正畸变后的参数    具体指哪些参数呢
        /// 
        private CalibrationParameters calibrationParametersRectified;

        /// 
        /// Stereo parameters for current ZED camera after rectification (undistorted).
        /// 校正后当前ZED摄像机的stereo参数(未失真)。
        /// Lance:矫正畸变后的参数    具体指哪些参数呢
        /// 
        public CalibrationParameters CalibrationParametersRectified
        {
            get { return calibrationParametersRectified; }
        }

        /// 
        /// Camera model - ZED or ZED Mini.
        /// 相机型号
        /// Lance:我的是mini
        /// 
        private sl.MODEL cameraModel;

        /// 
        /// Camera model - ZED or ZED Mini.
        /// 相机型号-ZED或ZED Mini。
        /// 
        public sl.MODEL CameraModel
        {
            get { return cameraModel; }
        }


        /// 
        /// Whether the camera has been successfully initialized.
        /// 相机是否已成功初始化。
        /// 
        private bool cameraReady = false;

        /// 
        /// Whether the camera has been successfully initialized.
        /// 相机是否成功初始化
        /// 
        public bool IsCameraReady
        {
            get { return cameraReady; }
        }

        /// 
        /// Whether the current device (ZED or ZED Mini) should be used for pass-through AR.
        /// True if using ZED Mini, false if using ZED.
        /// 直通AR是否应使用当前设备(ZED或ZED Mini)。
        /// 如果使用ZED Mini,则为true,如果使用ZED,则为false。
        /// Note: the plugin will allow using the original ZED
        /// for pass-through but it will feel quite uncomfortable due to the baseline.
        /// 该插件将允许使用原始的ZED作为AR的设备,但是由于基线不同,它会让用户感到非常不舒服
        /// Lance:最好是用ZED设备的mini版本
        public bool IsHmdCompatible //判断AR头盔是否兼容
        {
            get { return cameraModel == sl.MODEL.ZED_M; }
        }

        /// 
        /// Camera ID (for multiple cameras)
        /// 相机的序号(用于多个cameras的情景)
        /// Lance:  这边的camera ID  应该指的是ZED的实体相机,而不是我们实例化camera的对象
        /// 
        public int CameraID = 0; //在sdk3.2版本中似乎在实例化sl.Camera()的时候需要传入这个ID 在C#的API设置中遇到了这个问题

        // /// 
        // /// Layer that the ZED can't see, but overlay cameras created by ZEDMeshRenderer and ZEDPlaneRenderer can.
        // ///
        // /// 
        // int tagInvisibleToZED = 16;
        /// 
        /// Layer that the ZED can't see, but overlay cameras created by ZEDMeshRenderer and ZEDPlaneRenderer can.
        /// ZED无法看到的图层,但是可以覆盖由ZEDMeshRenderer和ZEDPlaneRenderer创建的摄影机。
        /// Lance:这边设置的是一个图层标签,标签对应的图层不会在AR模式下被看到,这边还不是特别理解,先往下看吧
        /// 
        public int TagInvisibleToZED
        {
            get { return ZEDLayers.tagInvisibleToZED; }
        }
        public const int brightnessDefault = 4; //设置亮度
        public const int contrastDefault = 4; //对比度
        public const int hueDefault = 0; // 色相类型
        public const int saturationDefault = 4; // 饱和度
        public const int sharpnessDefault = 3; // 清晰度
        public const int gammaDefault = 5; //伽马默认值  什么是伽马值(https://www.zhihu.com/question/27467127)——Lance
        public const int whitebalanceDefault = 2600; // 白平衡
        #endregion
        #region DLL Calls  就注释一部分,这部分的内容我们一般不会做修改。

        /// 
        /// Current Plugin Version.
        /// 当前插件版本
        /// 
        public static readonly System.Version PluginVersion = new System.Version(3, 1, 0); //正常这个版本是3.1.0


        /******** DLL members ***********/
        //DllImport用于载入由C或者C++编写的动态链接库,这种动态链接库属于非托管类型。其实ZED官方在github已经把这个动态链接库转换成.net托管类型的动态链接库了,可以由C#直接引用
        //估计在下一版本的插件上会弃用这部分的代码,而直接引用 C#的APi
        [DllImport(nameDll, EntryPoint = "GetRenderEventFunc")] //用DllImport载入C的动态链接库,入口点为"GetRenderEvenFunc",
        private static extern IntPtr
            GetRenderEventFunc(); //入口点函数声明    extern 指的是外部链接库定义的对象 什么是IntPtr:https://blog.csdn.net/ABC13222880223/article/details/100192245

        [DllImport(nameDll, EntryPoint = "dllz_register_callback_debuger")]
        private static extern void dllz_register_callback_debuger(DebugCallback callback);


        /*
          * Utils function.
          *实用程序功能。
          */

        [DllImport(nameDll, EntryPoint = "dllz_unload_all_instances")]
        private static extern void dllz_unload_all_instances();

        [DllImport(nameDll, EntryPoint = "dllz_unload_instance")]
        private static extern void dllz_unload_instance(int id);

        [DllImport(nameDll, EntryPoint = "dllz_find_usb_device")]
        private static extern bool dllz_find_usb_device(USB_DEVICE dev);

        /*
          * Create functions
          */
        [DllImport(nameDll, EntryPoint = "dllz_create_camera")]
        private static extern bool dllz_create_camera(int cameraID, bool verbose);


        /*
        * Opening function (Opens camera and creates textures).
        * 打开功能(打开相机并创建纹理)。
        */
        [DllImport(nameDll, EntryPoint = "dllz_open")]
        private static extern int dllz_open(int cameraID, ref dll_initParameters parameters,
            System.Text.StringBuilder svoPath, System.Text.StringBuilder ipStream, int portStream,
            System.Text.StringBuilder output, System.Text.StringBuilder opt_settings_path);


        /*
         * Close function.
         * 关闭相机
         */
        [DllImport(nameDll, EntryPoint = "dllz_close")]
        private static extern void dllz_close(int cameraID);


        /*
         * Grab function.
         * 数据采集函数
         */
        [DllImport(nameDll, EntryPoint = "dllz_grab")]
        private static extern int dllz_grab(int cameraID, ref sl.RuntimeParameters runtimeParameters);


        /*
        * Recording functions.
         * 录制函数
        */
        [DllImport(nameDll, EntryPoint = "dllz_enable_recording")]
        private static extern int dllz_enable_recording(int cameraID, byte[] video_filename, int compresssionMode);

        [DllImport(nameDll, EntryPoint = "dllz_disable_recording")]
        private static extern bool dllz_disable_recording(int cameraID);


        /*
        * Texturing functions.
         * 纹理相关的函数
         * 纹理、着色器、的概念http://blog.sina.com.cn/s/blog_14d5b8dff0102x5kq.html
         * Lance:纹理就是实例化的着色器。纹理和着色器的关系更像是一个实体和属性的关系,   属性必须依附实体,实体通过属性彰显。  纹理就是一个实体,着色器是纹理的必有属性。
        */
        [DllImport(nameDll, EntryPoint = "dllz_retrieve_textures")]
        private static extern void dllz_retrieve_textures(int cameraID); //获取纹理

        [DllImport(nameDll, EntryPoint = "dllz_get_updated_textures_timestamp")]
        private static extern ulong dllz_get_updated_textures_timestamp(int cameraID); //更新纹理的时间戳

        [DllImport(nameDll, EntryPoint = "dllz_swap_textures")]
        private static extern void dllz_swap_textures(int cameraID); // 交互纹理?这是什么含义


        [DllImport(nameDll, EntryPoint = "dllz_register_texture_image_type")]
        private static extern int dllz_register_texture_image_type(int cameraID, int option, IntPtr id,
            Resolution resolution); // 获取图像类型的纹理,指的是平面类型的纹理吗?  觉得image 类型和 measure类型好迷糊

        [DllImport(nameDll, EntryPoint = "dllz_register_texture_measure_type")]
        private static extern int dllz_register_texture_measure_type(int cameraID, int option, IntPtr id,
            Resolution resolution); //注册 测量类型的纹理

        [DllImport(nameDll, EntryPoint = "dllz_unregister_texture_measure_type")]
        private static extern int dllz_unregister_texture_measure_type(int cameraID, int option); //释放注册测量类型的数据


        [DllImport(nameDll, EntryPoint = "dllz_unregister_texture_image_type")]
        private static extern int dllz_unregister_texture_image_type(int cameraID, int option); //释放图片类型的纹理

        [DllImport(nameDll, EntryPoint = "dllz_get_copy_mat_texture_image_type")]
        private static extern IntPtr dllz_get_copy_mat_texture_image_type(int cameraID, int option); //返回平面图像类型的数据

        [DllImport(nameDll, EntryPoint = "dllz_get_copy_mat_texture_measure_type")]
        private static extern IntPtr dllz_get_copy_mat_texture_measure_type(int cameraID, int option); //返回测量图像类型的数据


        /*
         * Camera control functions.
         * 相机控制函数
         */

        [DllImport(nameDll, EntryPoint = "dllz_set_video_settings")]
        private static extern void dllz_set_video_settings(int id, int mode, int value); //设置视频流

        [DllImport(nameDll, EntryPoint = "dllz_get_video_settings")]
        private static extern int dllz_get_video_settings(int id, int mode); //获得当前视频流的设置

        [DllImport(nameDll, EntryPoint = "dllz_set_roi_for_aec_agc")]
        private static extern int dllz_set_roi_for_aec_agc(int id, int side, iRect roi, bool reset); //不清楚什么功能

        [DllImport(nameDll, EntryPoint = "dllz_get_roi_for_aec_agc")]
        private static extern int dllz_get_roi_for_aec_agc(int id, int side, ref iRect roi);


        [DllImport(nameDll, EntryPoint = "dllz_get_input_type")]
        private static extern int dllz_get_input_type(int cameraID); //获得输入类型 指的是USB或者其他连接方式

        [DllImport(nameDll, EntryPoint = "dllz_set_camera_fps")]
        private static extern void dllz_set_camera_fps(int cameraID, int fps); //设置帧率

        [DllImport(nameDll, EntryPoint = "dllz_get_camera_fps")]
        private static extern float dllz_get_camera_fps(int cameraID); //获得帧率

        [DllImport(nameDll, EntryPoint = "dllz_get_width")]
        private static extern int dllz_get_width(int cameraID); //获得图像数据的宽度

        [DllImport(nameDll, EntryPoint = "dllz_get_height")]
        private static extern int dllz_get_height(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_calibration_parameters")]
        private static extern IntPtr dllz_get_calibration_parameters(int cameraID, bool raw);

        [DllImport(nameDll, EntryPoint = "dllz_get_camera_model")]
        private static extern int dllz_get_camera_model(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_camera_firmware")]
        private static extern int dllz_get_camera_firmware(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_sensors_firmware")]
        private static extern int dllz_get_sensors_firmware(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_zed_serial")]
        private static extern int dllz_get_zed_serial(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_camera_imu_transform")]
        private static extern void dllz_get_camera_imu_transform(int cameraID, ulong timeStamp, bool useLatency,
            out Vector3 translation, out Quaternion rotation);

        [DllImport(nameDll, EntryPoint = "dllz_is_zed_connected")]
        private static extern int dllz_is_zed_connected();

        [DllImport(nameDll, EntryPoint = "dllz_get_camera_Timestamp")]
        private static extern ulong dllz_get_camera_timestamp(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_current_Timestamp")]
        private static extern ulong dllz_get_current_timestamp(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_image_updater_time_stamp")]
        private static extern ulong dllz_get_image_updater_time_stamp(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_frame_dropped_count")]
        private static extern uint dllz_get_frame_dropped_count(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_frame_dropped_percent")]
        private static extern float dllz_get_frame_dropped_percent(int cameraID);

        /*
         * SVO control functions.
         */

        [DllImport(nameDll, EntryPoint = "dllz_set_svo_position")]
        private static extern void dllz_set_svo_position(int cameraID, int frame);

        [DllImport(nameDll, EntryPoint = "dllz_get_svo_number_of_frames")]
        private static extern int dllz_get_svo_number_of_frames(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_svo_position")]
        private static extern int dllz_get_svo_position(int cameraID);


        /*
         * Depth Sensing utils functions.
         */
        /* Removed as of ZED SDK v3.0.
       [DllImport(nameDll, EntryPoint = "dllz_set_confidence_threshold")]
       private static extern void dllz_set_confidence_threshold(int cameraID, int threshold);
       [DllImport(nameDll, EntryPoint = "dllz_set_depth_max_range_value")]
       private static extern void dllz_set_depth_max_range_value(int cameraID, float distanceMax);
       */

        [DllImport(nameDll, EntryPoint = "dllz_get_confidence_threshold")]
        private static extern int dllz_get_confidence_threshold(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_depth_max_range_value")]
        private static extern float dllz_get_depth_max_range_value(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_depth_value")]
        private static extern float dllz_get_depth_value(int cameraID, uint x, uint y);

        [DllImport(nameDll, EntryPoint = "dllz_get_distance_value")]
        private static extern float dllz_get_distance_value(int cameraID, uint x, uint y);

        [DllImport(nameDll, EntryPoint = "dllz_get_normal_value")]
        private static extern int dllz_get_normal_value(int cameraID, uint x, uint y, out Vector4 value);

        [DllImport(nameDll, EntryPoint = "dllz_get_xyz_value")]
        private static extern int dllz_get_xyz_value(int cameraID, uint x, uint y, out Vector4 value);

        [DllImport(nameDll, EntryPoint = "dllz_get_depth_min_range_value")]
        private static extern float dllz_get_depth_min_range_value(int cameraID);


        /*
         * Motion Tracking functions.
         */
        [DllImport(nameDll, EntryPoint = "dllz_enable_tracking")]
        private static extern int dllz_enable_tracking(int cameraID, ref Quaternion quat, ref Vector3 vec,
            bool enableSpatialMemory = false, bool enablePoseSmoothing = false, bool enableFloorAlignment = false,
            bool trackingIsStatic = false, bool enableIMUFusion = true, System.Text.StringBuilder aeraFilePath = null);

        [DllImport(nameDll, EntryPoint = "dllz_disable_tracking")]
        private static extern void dllz_disable_tracking(int cameraID, System.Text.StringBuilder path);

        [DllImport(nameDll, EntryPoint = "dllz_save_current_area")]
        private static extern int dllz_save_current_area(int cameraID, System.Text.StringBuilder path);

        [DllImport(nameDll, EntryPoint = "dllz_get_position_data")]
        private static extern int dllz_get_position_data(int cameraID, ref Pose pose, int reference_frame);

        [DllImport(nameDll, EntryPoint = "dllz_get_position")]
        private static extern int dllz_get_position(int cameraID, ref Quaternion quat, ref Vector3 vec,
            int reference_frame);

        [DllImport(nameDll, EntryPoint = "dllz_get_position_at_target_frame")]
        private static extern int dllz_get_position_at_target_frame(int cameraID, ref Quaternion quaternion,
            ref Vector3 translation, ref Quaternion targetQuaternion, ref Vector3 targetTranslation,
            int reference_frame);

        [DllImport(nameDll, EntryPoint = "dllz_transform_pose")]
        private static extern void dllz_transform_pose(ref Quaternion quaternion, ref Vector3 translation,
            ref Quaternion targetQuaternion, ref Vector3 targetTranslation);

        [DllImport(nameDll, EntryPoint = "dllz_reset_tracking")]
        private static extern int dllz_reset_tracking(int cameraID, Quaternion rotation, Vector3 translation);

        [DllImport(nameDll, EntryPoint = "dllz_reset_tracking_with_offset")]
        private static extern int dllz_reset_tracking_with_offset(int cameraID, Quaternion rotation,
            Vector3 translation, Quaternion offsetQuaternion, Vector3 offsetTranslation);

        [DllImport(nameDll, EntryPoint = "dllz_estimate_initial_position")]
        private static extern int dllz_estimate_initial_position(int cameraID, ref Quaternion quaternion,
            ref Vector3 translation, int countSuccess, int countTimeout);

        [DllImport(nameDll, EntryPoint = "dllz_set_imu_prior_orientation")]
        private static extern int dllz_set_imu_prior_orientation(int cameraID, Quaternion rotation);

        [DllImport(nameDll, EntryPoint = "dllz_get_internal_imu_orientation")]
        private static extern int dllz_get_internal_imu_orientation(int cameraID, ref Quaternion rotation,
            int reference_time);

        [DllImport(nameDll, EntryPoint = "dllz_get_internal_sensors_data")]
        private static extern int dllz_get_internal_sensors_data(int cameraID, ref SensorsData imuData,
            int reference_time);

        [DllImport(nameDll, EntryPoint = "dllz_get_area_export_state")]
        private static extern int dllz_get_area_export_state(int cameraID);

        /*
        * Spatial Mapping functions.
        */
        [DllImport(nameDll, EntryPoint = "dllz_enable_spatial_mapping")]
        private static extern int dllz_enable_spatial_mapping(int cameraID, float resolution_meter,
            float max_range_meter, int saveTexture);

        [DllImport(nameDll, EntryPoint = "dllz_disable_spatial_mapping")]
        private static extern void dllz_disable_spatial_mapping(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_pause_spatial_mapping")]
        private static extern void dllz_pause_spatial_mapping(int cameraID, bool status);

        [DllImport(nameDll, EntryPoint = "dllz_request_mesh_async")]
        private static extern void dllz_request_mesh_async(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_get_mesh_request_status_async")]
        private static extern int dllz_get_mesh_request_status_async(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_update_mesh")]
        private static extern int dllz_update_mesh(int cameraID, int[] nbVerticesInSubemeshes,
            int[] nbTrianglesInSubemeshes, ref int nbSubmeshes, int[] updatedIndices, ref int nbVertices,
            ref int nbTriangles, int nbSubmesh);

        [DllImport(nameDll, EntryPoint = "dllz_retrieve_mesh")]
        private static extern int dllz_retrieve_mesh(int cameraID, Vector3[] vertices, int[] triangles, int nbSubmesh,
            Vector2[] uvs, IntPtr textures);

        [DllImport(nameDll, EntryPoint = "dllz_save_mesh")]
        private static extern bool dllz_save_mesh(int cameraID, string filename, MESH_FILE_FORMAT format);

        [DllImport(nameDll, EntryPoint = "dllz_load_mesh")]
        private static extern bool dllz_load_mesh(int cameraID, string filename, int[] nbVerticesInSubemeshes,
            int[] nbTrianglesInSubemeshes, ref int nbSubmeshes, int[] updatedIndices, ref int nbVertices,
            ref int nbTriangles, int nbMaxSubmesh, int[] textureSize = null);

        [DllImport(nameDll, EntryPoint = "dllz_apply_texture")]
        private static extern bool dllz_apply_texture(int cameraID, int[] nbVerticesInSubemeshes,
            int[] nbTrianglesInSubemeshes, ref int nbSubmeshes, int[] updatedIndices, ref int nbVertices,
            ref int nbTriangles, int[] textureSize, int nbSubmesh);

        [DllImport(nameDll, EntryPoint = "dllz_filter_mesh")]
        private static extern bool dllz_filter_mesh(int cameraID, FILTER meshFilter, int[] nbVerticesInSubemeshes,
            int[] nbTrianglesInSubemeshes, ref int nbSubmeshes, int[] updatedIndices, ref int nbVertices,
            ref int nbTriangles, int nbSubmesh);

        [DllImport(nameDll, EntryPoint = "dllz_get_spatial_mapping_state")]
        private static extern int dllz_get_spatial_mapping_state(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_spatial_mapping_merge_chunks")]
        private static extern void dllz_spatial_mapping_merge_chunks(int cameraID, int numberFaces,
            int[] nbVerticesInSubemeshes, int[] nbTrianglesInSubemeshes, ref int nbSubmeshes, int[] updatedIndices,
            ref int nbVertices, ref int nbTriangles, int nbSubmesh);

        [DllImport(nameDll, EntryPoint = "dllz_spatial_mapping_get_gravity_estimation")]
        private static extern void dllz_spatial_mapping_get_gravity_estimation(int cameraID, ref Vector3 v);

        /*
         * Plane Detection functions (starting v2.4)
         */
        [DllImport(nameDll, EntryPoint = "dllz_find_floor_plane")]
        private static extern IntPtr dllz_find_floor_plane(int cameraID, out Quaternion rotation,
            out Vector3 translation, Vector3 priorQuaternion, Vector3 priorTranslation);

        [DllImport(nameDll, EntryPoint = "dllz_find_plane_at_hit")]
        private static extern IntPtr dllz_find_plane_at_hit(int cameraID, Vector2 HitPixel, bool refine);

        [DllImport(nameDll, EntryPoint = "dllz_convert_floorplane_to_mesh")]
        private static extern int dllz_convert_floorplane_to_mesh(int cameraID, Vector3[] vertices, int[] triangles,
            out int numVertices, out int numTriangles);

        [DllImport(nameDll, EntryPoint = "dllz_convert_hitplane_to_mesh")]
        private static extern int dllz_convert_hitplane_to_mesh(int cameraID, Vector3[] vertices, int[] triangles,
            out int numVertices, out int numTriangles);


        /*
         * Streaming Module functions (starting v2.8)
         */
        [DllImport(nameDll, EntryPoint = "dllz_enable_streaming")]
        private static extern int dllz_enable_streaming(int cameraID, sl.STREAMING_CODEC codec, uint bitrate,
            ushort port, int gopSize, int adaptativeBitrate, int chunk_size);

        [DllImport(nameDll, EntryPoint = "dllz_is_streaming_enabled")]
        private static extern int dllz_is_streaming_enabled(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_disable_streaming")]
        private static extern void dllz_disable_streaming(int cameraID);


        /*
        * Objects Detection functions (starting v3.0)
        */
        [DllImport(nameDll, EntryPoint = "dllz_enable_objects_detection")]
        private static extern int dllz_enable_objects_detection(int cameraID,
            ref dll_ObjectDetectionParameters od_params);

        [DllImport(nameDll, EntryPoint = "dllz_disable_objects_detection")]
        private static extern void dllz_disable_objects_detection(int cameraID);

        [DllImport(nameDll, EntryPoint = "dllz_pause_objects_detection")]
        private static extern void dllz_pause_objects_detection(int cameraID, bool status);

        [DllImport(nameDll, EntryPoint = "dllz_retrieve_objects_data")]
        private static extern int dllz_retrieve_objects_data(int cameraID,
            ref dll_ObjectDetectionRuntimeParameters od_params, ref ObjectsFrameSDK objFrame);


        /*
        * Save utils function
        */
        [DllImport(nameDll, EntryPoint = "dllz_save_current_image")]
        private static extern int dllz_save_current_image(int cameraID, VIEW view, string filename);

        [DllImport(nameDll, EntryPoint = "dllz_save_current_depth")]
        private static extern int dllz_save_current_depth(int cameraID, int side, string filename);

        [DllImport(nameDll, EntryPoint = "dllz_save_current_point_cloud")]
        private static extern int dllz_save_current_point_cloud(int cameraID, int side, string filename);

        /*
         * Specific plugin functions
         */
        [DllImport(nameDll, EntryPoint = "dllz_check_plugin")]
        private static extern int dllz_check_plugin(int major, int minor);

        [DllImport(nameDll, EntryPoint = "dllz_get_sdk_version")]
        private static extern IntPtr dllz_get_sdk_version();

        [DllImport(nameDll, EntryPoint = "dllz_compute_offset")]
        private static extern void dllz_compute_offset(float[] A, float[] B, int nbVectors, float[] C);

        [DllImport(nameDll, EntryPoint = "dllz_compute_optical_center_offsets")]
        private static extern System.IntPtr dllz_compute_optical_center_offsets(ref Vector4 calibLeft,
            ref Vector4 calibRight, sl.Resolution imageResolution, float planeDistance);


        /*
         * Retreieves used by mat
         */
        [DllImport(nameDll, EntryPoint = "dllz_retrieve_measure")]
        private static extern int dllz_retrieve_measure(int cameraID, System.IntPtr ptr, int type, int mem,
            sl.Resolution resolution);

        [DllImport(nameDll, EntryPoint = "dllz_retrieve_image")]
        private static extern int dllz_retrieve_image(int cameraID, System.IntPtr ptr, int type, int mem,
            sl.Resolution resolution);

        #endregion

        /// 
        /// 释放插件里面的所有实例
        /// 
        public static void UnloadPlugin() // 释放插件的所有实例
        {
            dllz_unload_all_instances();
        }

        /// 
        /// 释放指定id的实例
        /// 
        /// 
        public static void UnloadInstance(int id) //释放指定的实例
        {
            dllz_unload_instance(id);
        }

        /// 
        /// 计算偏移,用于校正ZED相机在Unity中的位姿
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void ComputeOffset(float[] A, float[] B, int nbVectors, ref Quaternion rotation,
            ref Vector3 translation)
        {
            float[] C = new float[16];
            if (A.Length != 4 * nbVectors || B.Length != 4 * nbVectors || C.Length != 16) return;
            dllz_compute_offset(A, B, nbVectors, C);

            Matrix4x4 m = Matrix4x4.identity;
            Float2Matrix(ref m, C);

            rotation = Matrix4ToQuaternion(m);
            Vector4 t = m.GetColumn(3);
            translation.x = t.x;
            translation.y = t.y;
            translation.z = t.z;
        }

        /// 
        /// Return a string from a pointer to a char. Used in GetSDKVersion().
        /// 从指向char的指针返回字符串。在GetSDKVersion()中使用。
        /// 
        /// Pointer to a char.
        /// The char as a string.
        private static string PtrToStringUtf8(IntPtr ptr)
        {
            if (ptr == IntPtr.Zero)
            {
                return "";
            }

            int len = 0;
            while (Marshal.ReadByte(ptr, len) != 0)
                len++;
            if (len == 0)
            {
                return "";
            }

            byte[] array = new byte[len];
            Marshal.Copy(ptr, array, 0, len);
            return System.Text.Encoding.ASCII.GetString(array);
        }

        /// 
        /// Displays a console message. Used to display C++ SDK messages in Unity's console.
        /// 显示控制台消息。用于在Unity的控制台中显示C ++ SDK消息。
        /// 
        /// 
        private static void DebugMethod(string message)
        {
            Debug.Log("[ZED plugin]: " + message);
        }

        /// 
        /// Convert a pointer to a char into an array of bytes. Used to send file names to SDK for SVO recording.
        /// 将指向char的指针转换为字节数组。用于将文件名发送到SDK以进行SVO记录。
        /// 
        /// Pointer to a char.
        /// The array.
        private static byte[] StringUtf8ToByte(string str)
        {
            byte[] array = System.Text.Encoding.ASCII.GetBytes(str);
            return array;
        }

        /// 
        /// Gets the max FPS for each resolution setting. Higher FPS will cause lower GPU performance.
        /// 获取每个分辨率设置的最大FPS。较高的FPS将导致较低的GPU性能。
        /// Lance:后面指的是越高帧率将要求更好的GPU性能
        /// 
        /// 
        /// The resolution
        static private uint GetFpsForResolution(RESOLUTION reso)
        {
            if (reso == RESOLUTION.HD1080) return 30;
            else if (reso == RESOLUTION.HD2K) return 15;
            else if (reso == RESOLUTION.HD720) return 60;
            else if (reso == RESOLUTION.VGA) return 100;
            return 30;
        }

        /// 
        /// Get a quaternion from a matrix with a minimum size of 3x3.
        /// 从最小尺寸为3x3的矩阵中获取四元数。
        /// Lance:四元素是三维旋转的另外一种数学描述    什么是四元素:https://blog.csdn.net/qq_36537774/article/details/86533999
        /// 
        /// The matrix.
        /// A quaternion which contains the matrix's rotation.
        /// 包含矩阵旋转的四元数
        public static Quaternion Matrix4ToQuaternion(Matrix4x4 m)
        {
            Quaternion q = new Quaternion();
            q.w = Mathf.Sqrt(Mathf.Max(0, 1 + m[0, 0] + m[1, 1] + m[2, 2])) / 2;
            q.x = Mathf.Sqrt(Mathf.Max(0, 1 + m[0, 0] - m[1, 1] - m[2, 2])) / 2;
            q.y = Mathf.Sqrt(Mathf.Max(0, 1 - m[0, 0] + m[1, 1] - m[2, 2])) / 2;
            q.z = Mathf.Sqrt(Mathf.Max(0, 1 - m[0, 0] - m[1, 1] + m[2, 2])) / 2;
            q.x *= Mathf.Sign(q.x * (m[2, 1] - m[1, 2]));
            q.y *= Mathf.Sign(q.y * (m[0, 2] - m[2, 0]));
            q.z *= Mathf.Sign(q.z * (m[1, 0] - m[0, 1]));
            return q;
        }

        /// 
        /// Performs a rigid transform.
        /// 执行刚性变换。
        /// 
        ///  原始角度
        ///  原始位置
        ///   目标角度
        ///  目标位置
        public static void TransformPose(ref Quaternion quaternion, ref Vector3 translation,
            ref Quaternion targetQuaternion, ref Vector3 targetTranslation)
        {
            dllz_transform_pose(ref quaternion, ref translation, ref targetQuaternion, ref targetTranslation);
        }

        /// 
        /// Checks that the ZED plugin's dependencies are installed.
        /// 检查是否已安装ZED插件的依赖项。
        /// 
        public static bool CheckPlugin()
        {
            try
            {
                int res = dllz_check_plugin(PluginVersion.Major, PluginVersion.Minor);
                if (res != 0)
                {
                    Debug.Log("Error : " + res);
                    //0 = installed SDK is compatible with plugin. 1 otherwise.
                    Debug.LogError(ZEDLogMessage.Error2Str(ZEDLogMessage.ERROR.SDK_DEPENDENCIES_ISSUE));
                    return false;
                }
            }
            catch (DllNotFoundException) //In case could not resolve the dll/.so
            {
                Debug.Log("DllNotFoundException");
                Debug.LogError(ZEDLogMessage.Error2Str(ZEDLogMessage.ERROR.SDK_DEPENDENCIES_ISSUE));
                return false;
            }

            pluginIsReady = true;
            return true;
        }

        /// 
        /// Checks if the USB device of a 'brand' type is connected. Used to check if a VR headset are connected
        /// for display in ZEDManager's Inspector.
        /// 检查是否已连接“brand”类型的USB设备。
        /// 用于检查是否连接了VR耳机以在ZEDManager的Inspector中显示。
        /// 
        /// True, if USB device connected was found, false otherwise.
        /// Type.
        public static bool CheckUSBDeviceConnected(USB_DEVICE Type)
        {
            if (dllz_find_usb_device(Type))
                return true;
            else
                return false;
        }


        /// 
        /// Private constructor. Initializes lists to hold references to textures and texture requests.
        /// 私有构造函数。初始化列表以保存对纹理和纹理请求的引用。
        /// Lance:估计是后面发现其他类里面需要用 又改成public形式
        /// 从下面的代码来看,实例化一个ZEDCamera相机相当于实例化图像的纹理列表?
        /// 
        public ZEDCamera()
        {
            //Create the textures
            textures = new Dictionary<int, Dictionary<int, Texture2D>>(); // 以字典的形式来组织,最内层的纹理的类型是2D的?
            texturesRequested = new List<TextureRequested>(); //纹理请求列表
        }

        /// 
        /// Create a camera in Live mode (input comes from a connected ZED device, not SVO playback).
        /// 在实时模式下创建相机(输入来自所连接的ZED设备,而不是SVO播放)。
        /// 
        /// True to create detailed log file of SDK calls at the cost of performance.
        /// 为True会创建SDK调用的详细日志文件,但会降低性能。
        public bool CreateCamera(int cameraID, bool verbose)
        {
            string infoSystem = SystemInfo.graphicsDeviceType.ToString().ToUpper();
            if (!infoSystem.Equals("DIRECT3D11") && !infoSystem.Equals("OPENGLCORE"))
            {
                throw new Exception("The graphic library [" + infoSystem + "] is not supported");
            }

            CameraID = cameraID;
            //tagOneObject += cameraID;
            return dllz_create_camera(cameraID, verbose);
        }

        /// 
        /// Closes the camera and deletes all textures.
        /// Once destroyed, you need to recreate a camera instance to restart again.
        /// 关闭相机并删除所有纹理。
        /// 一旦销毁,您需要重新创建相机实例以重新启动。
        /// 
        public void Destroy()
        {
            cameraReady = false;
            dllz_close(CameraID);
            DestroyAllTexture();
        }

        /// 
        /// DLL-friendly version of InitParameters (found in ZEDCommon.cs).
        /// DLL友好的InitParameters版本(可在ZEDCommon.cs中找到)。
        /// Lance: 定义一个参数结构体,里面的参数变量大部分都是由sl定义的类型,在ZEDCommon.cs中引用
        /// 
        [StructLayout(LayoutKind.Sequential)]
        public struct dll_initParameters
        {
            public sl.INPUT_TYPE inputType;

            /// 
            /// Resolution the ZED will be set to.
            /// 
            public sl.RESOLUTION resolution; //分辨率

            /// 
            /// Desired camera FPS. Max is set by resolution.
            /// 
            public int cameraFps; //相机帧率

            /// 
            /// ID for identifying which of multiple connected ZEDs to use.
            /// 
            public int cameraDeviceID; //相机设备ID

            /// 
            /// True to flip images horizontally.
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool cameraImageFlip; //是否水平镜像

            /// 
            /// True to disable self-calibration, using unoptimized optional calibration parameters.
            /// False is recommended for optimized calibration.
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool cameraDisableSelfCalib; // 如果为真,就不启动相机自身的自校准

            /// 
            /// True if depth relative to the right sensor should be computed.
            /// 如果应计算相对于右传感器的深度,则为True。
            /// Lance: 一般情况下我们只用左相机的深度图,如果需要右相机的深度图的话,就把这个变量设置为真
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool enableRightSideMeasure;

            /// 
            /// True to skip dropped frames during SVO playback.
            /// 设为True可在SVO播放期间跳过掉帧。
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool svoRealTimeMode;

            /// 
            /// Quality level of depth calculations. Higher settings improve accuracy but cost performance.
            /// 深度计算的质量级别。较高的设置可以提高准确性,但可以提高性价比。
            /// 
            public sl.DEPTH_MODE depthMode;

            /// 
            /// True to stabilize the depth map. Recommended.
            /// 为真:实现稳定的深度匹配。 推荐使用
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool depthStabilization;

            /// 
            /// Minimum distance from the camera from which depth will be computed, in the defined coordinateUnit.
            /// 在定义的coordinateUnit中,深度图像的最小距离。
            /// 
            public float depthMinimumDistance;

            /// 
            /// Maximum distance that can be computed.
            /// 可以计算的最大深度距离。
            /// 
            public float depthMaximumDistance;

            /// 
            /// Coordinate unit for all measurements (depth, tracking, etc.). Meters are recommended for Unity.
            /// 所有测量的坐标单位(深度,跟踪等)。在Unity中,最好采用"米"为单位。
            /// 
            public UNIT coordinateUnit;

            /// 
            /// Defines order and direction of coordinate system axes. Unity uses left-handed, Y up, so this setting is recommended.
            /// 定义坐标系轴的顺序和方向。 Unity使用左手坐标系,向上是Y方向,因此建议使用此设置。
            /// 
            public COORDINATE_SYSTEM coordinateSystem;

            /// 
            /// ID of the graphics card on which the ZED's computations will be performed.
            /// GPU的序号,ZED相关的运算在这个GPU上运行。
            /// 
            public int sdkGPUId;

            /// 
            /// True for the SDK to provide text feedback.
            /// 真:SDK的信息反馈
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool sdkVerbose;

            /// 
            /// True if sensors are required, false will not trigger an error if sensors are missing.
            /// 如果需要传感器,则为true;如果缺少传感器,则为false不会触发错误。
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool sensorsRequired;

            /// 
            /// Whether to enable improved color/gamma curves added in ZED SDK 3.0.
            /// 是否启用ZED SDK 3.0中添加的改进的颜色/伽玛曲线。
            /// 
            [MarshalAs(UnmanagedType.U1)] public bool enableImageEnhancement;

            /// 
            /// Copy constructor. Takes values from
            /// Unity-suited InitParameters class.
            /// 复制构造函数。从适用于Unity的InitParameters类中获取值。
            /// 
            /// 
            public dll_initParameters(InitParameters init)
            {
                inputType = init.inputType;
                resolution = init.resolution;
                cameraFps = init.cameraFPS;
                svoRealTimeMode = init.svoRealTimeMode;
                coordinateUnit = init.coordinateUnit;
                depthMode = init.depthMode;
                depthMinimumDistance = init.depthMinimumDistance;
                depthMaximumDistance = init.depthMaximumDistance;
                cameraImageFlip = init.cameraImageFlip;
                enableRightSideMeasure = init.enableRightSideMeasure;
                cameraDisableSelfCalib = init.cameraDisableSelfCalib;
                sdkVerbose = init.sdkVerbose;
                sdkGPUId = init.sdkGPUId;
                cameraDeviceID = init.cameraDeviceID;
                coordinateSystem = init.coordinateSystem;
                depthStabilization = init.depthStabilization;
                sensorsRequired = init.sensorsRequired;
                enableImageEnhancement = init.enableImageEnhancement;
            }
        }


        /// 
        /// Checks if the ZED camera is plugged in, opens it, and initializes the projection matix and command buffers for updating textures.
        /// 检查是否插入了ZED摄像机,将其打开,然后初始化投影矩阵和命令缓冲区以更新贴图。
        /// 
        /// Class with all initialization settings.
        /// A newly-instantiated InitParameters will have recommended default values
        /// 具有所有初始化设置的类。
        /// 新实例化的InitParameters将具有建议的默认值。.
        /// ERROR_CODE: The error code gives information about the internal connection process.
        /// If SUCCESS is returned, the camera is ready to use. Every other code indicates an error.
        /// ERROR_CODE:错误代码提供有关内部连接过程的信息。
        /// 如果返回SUCCESS,则可以使用相机。其他所有代码均指示错误。
        public ERROR_CODE Init(ref InitParameters initParameters) //返回的是错误提示信息
        {
            //Update values with what we're about to pass to the camera.
            //用我们将要传递给相机的值更新值。
            currentResolution = initParameters.resolution; //分辨率
            fpsMax = GetFpsForResolution(currentResolution); //最大帧率,与当前分辨率有关
            if (initParameters.cameraFPS == 0) // 当前帧率是否为0
            {
                initParameters.cameraFPS = (int) fpsMax; //如果没有指定就直接采用最大的帧率
            }

            dll_initParameters
                initP = new dll_initParameters(
                    initParameters); //DLL-friendly version of InitParameters.   能够被dll文件接收的参数对象
            initP.coordinateSystem =
                COORDINATE_SYSTEM
                    .LEFT_HANDED_Y_UP; //Left-hand, Y-up is Unity's coordinate system, so we match that.  左手系坐标系
            int v = dllz_open(CameraID, ref initP,
                new System.Text.StringBuilder(initParameters.pathSVO, initParameters.pathSVO.Length),
                new System.Text.StringBuilder(initParameters.ipStream, initParameters.ipStream.Length),
                initParameters.portStream,
                new System.Text.StringBuilder(initParameters.sdkVerboseLogFile,
                    initParameters.sdkVerboseLogFile.Length),
                new System.Text.StringBuilder(initParameters.optionalSettingsPath,
                    initParameters.optionalSettingsPath
                        .Length)); // 打开相机,传入相机ID,初始参数的引用, SVO的路径, 流的JP和长度,端口号,sdk的日志文件,最优设置的路径,

            if ((ERROR_CODE) v != ERROR_CODE.SUCCESS) //判断是否成功
            {
                cameraReady = false; //没有成功
                return (ERROR_CODE) v; // 返回错误信息 下面的代码不再执行
            }

            //Set more values if the initialization was successful.
            // 如果初始化成功,则设置更多的参数值
            imageWidth = dllz_get_width(CameraID); //图片的宽
            imageHeight = dllz_get_height(CameraID); //图片的高

            if (imageWidth > 0 && imageHeight > 0) //说明相机有返回图片的参数
            {
                GetCalibrationParameters(false); //获得相机的标定参数  如果为false 就是给calibrationParametersRectified变量赋值一下
                FillProjectionMatrix(); // 填充投影变换矩阵,这个函数只需要调用一次
                baseline = calibrationParametersRectified.Trans[0]; // 基线赋值
                fov_H = calibrationParametersRectified.leftCam.hFOV * Mathf.Deg2Rad; //水平视野
                fov_V = calibrationParametersRectified.leftCam.vFOV * Mathf.Deg2Rad; //垂直视野
                cameraModel = GetCameraModel(); //获取相机的模型 这边指的是物理相机的模型
                cameraReady = true; //相机准备好了
                return (ERROR_CODE) v;
            }
            else
                return sl.ERROR_CODE.CAMERA_NOT_INITIALIZED; //未正确启动相机
        }


        /// 
        /// Fills the projection matrix with the parameters of the ZED. Needs to be called only once.
        /// This projection matrix is off-center.
        /// 用ZED的参数填充投影矩阵。只需要调用一次。
        /// 此投影矩阵偏离中心。
        /// Lance: 这个投影矩阵我还不确定是哪个坐标系到哪个坐标系的投影
        /// 
        /// 应该是Z方向上最远点,500应该是近似无穷远
        /// Z方向上最近点
        public void FillProjectionMatrix(float zFar = 500, float zNear = 0.1f)
        {
            CalibrationParameters parameters = GetCalibrationParameters(false); //获得是矫正过后的标定参数

            float fovx = parameters.leftCam.hFOV * Mathf.Deg2Rad; //水平视场角度   转换为弧度制
            float fovy = parameters.leftCam.vFOV * Mathf.Deg2Rad; //垂直视场角度   转换为弧度制

            float f_imageWidth = (float) ImageWidth; //图片宽度  指列数
            float f_imageHeight = (float) ImageHeight; //图片高度  指行数

            //Manually construct the matrix based on initialization/calibration values.
            //根据初始化,标定值,手动构建矩阵。
            // Lance: 明显感觉这个脚本写的没有ZEDManager的可读性好, 注释的内容比较少。下面是自己添加的变换矩阵示意图
            //     |Horizontal FoV,        0     , Horizontal offset   ,          0           |
            //     |       0      , Vertical FoV ,   Vertical offset   ,          0           |
            //     |       0      ,        0     , Near and far planes , Near and far planes  |
            //     |       0      ,        0     ,          -1         ,          0           |


            projection[0, 0] = 1.0f / Mathf.Tan(fovx * 0.5f); //Horizontal FoV.
            projection[0, 1] = 0;
            //Horizontal offset.  水平偏移量,  cx指图像的实际物理中心的x,  这个是由于镜片的加工误差,实际的镜头中心与图像中心并不完全重合
            projection[0, 2] =
                2.0f * ((f_imageWidth - 1.0f * parameters.leftCam.cx) / f_imageWidth) - 1.0f;
            projection[0, 3] = 0;

            projection[1, 0] = 0;
            projection[1, 1] = 1.0f / Mathf.Tan(fovy * 0.5f); //Vertical FoV.
            projection[1, 2] =
                -(2.0f * ((f_imageHeight - 1.0f * parameters.leftCam.cy) / f_imageHeight) -
                  1.0f); //Vertical offset.  垂直偏移
            projection[1, 3] = 0;

            projection[2, 0] = 0;
            projection[2, 1] = 0;
            projection[2, 2] = -(zFar + zNear) / (zFar - zNear); //Near and far planes.  最远点和最近点的平面  这个还不是很理解
            projection[2, 3] = -(2.0f * zFar * zNear) / (zFar - zNear); //Near and far planes.

            projection[3, 0] = 0;
            projection[3, 1] = 0;
            projection[3, 2] = -1;
            projection[3, 3] = 0.0f;
        }

        /// 
        /// Grabs a new image, rectifies it, and computes the disparity map and (optionally) the depth map.
        /// The grabbing function is typically called in the main loop in a separate thread.
        /// 抓取新图像,对其进行校正,然后计算视差和(可选)深度图。
        /// 通常在主循环中的单独线程中调用抓取函数。
        /// For more info, read about the SDK function it calls:
        /// 有关更多信息,请阅读有关其调用的SDK函数的信息:
        /// https://www.stereolabs.com/developers/documentation/API/v2.5.1/classsl_1_1Camera.html#afa3678a18dd574e162977e97d7cbf67b 
        /// Struct holding all grab parameters.保留所有抓取参数的结构体 
        /// the function returns false if no problem was encountered,
        /// true otherwise.如果没有遇到问题,该函数返回false,否则返回true。
        public sl.ERROR_CODE
            Grab(ref sl.RuntimeParameters runtimeParameters) // 发现这个函数并没有返回值,说明只是从上层告知下层相机说你给我采集新的一帧数据,但是采集完的数据并没有返回过来
        {
            return (sl.ERROR_CODE) dllz_grab(CameraID, ref runtimeParameters);
        }


        /// 
        /// Return the INPUT_TYPE currently used
        /// 返回当前使用的INPUT_TYPE
        /// Lance:指的是相机与电脑的连接类型,我的mini是USB3.0
        /// 
        /// 
        public sl.INPUT_TYPE GetInputType()
        {
            return (sl.INPUT_TYPE) dllz_get_input_type(CameraID);
        }

        /// 
        /// Creates a file for recording the ZED's output into a .SVO or .AVI video.
        /// 创建一个文件,用于将ZED的录制输出为.SVO或.AVI视频。
        /// An SVO is Stereolabs' own format designed for the ZED. It holds the video feed with timestamps
        /// as well as info about the camera used to record it.
        /// SVO是Stereolabs自己为ZED设计的格式。它包含带有时间戳的视频,以及有关用于记录它的摄像机的信息。
        /// Filename. Whether it ends with .svo or .avi defines its file type.文档名称。它以.svo还是.avi结尾定义其文件类型。
        /// How much compression to use,压缩模式
        /// An ERROR_CODE that defines if the file was successfully created and can be filled with images.
        /// 一个ERROR_CODE,它定义文件是否已成功创建并且可以写入图片数据。
        public ERROR_CODE EnableRecording(string videoFileName,
            SVO_COMPRESSION_MODE compressionMode = SVO_COMPRESSION_MODE.H264_BASED)
        {
            return (ERROR_CODE) dllz_enable_recording(CameraID, StringUtf8ToByte(videoFileName), (int) compressionMode);
        }


        /// 
        /// Stops recording to an SVO/AVI, if applicable, and closes the file.
        /// 停止记录到SVO / AVI(如果有),并关闭文件。
        /// 
        public bool DisableRecording()
        {
            return dllz_disable_recording(CameraID);
        }

        /// 
        /// Sets a new target frame rate for the camera. If it's not possible with the current resolution,
        /// the SDK will target the closest possible frame rate instead.
        /// 设置相机的新目标帧频。如果使用当前分辨率无法实现,
        /// SDK将以尽可能接近的帧速率为目标。
        /// 
        /// New target FPS.
        public void SetCameraFPS(int fps)
        {
            if (GetFpsForResolution(currentResolution) >= fps) // 当前分辨率下的最大帧率如果大于我们设置的大小
            {
                fpsMax = (uint) fps; //为什么要把最大帧率重新赋值???
            }

            dllz_set_camera_fps(CameraID, fps); //设置相机帧率
        }

        /// 
        /// Sets the position of the SVO file currently being read to a desired frame.
        /// 就是把SVO文件当前的位置空间用来存放指定的一帧呗
        /// 
        /// Index of the desired frame to be decoded.
        public void SetSVOPosition(int frame)
        {
            dllz_set_svo_position(CameraID, frame);
        }

        /// 
        /// Gets the current confidence threshold value for the disparity map (and by extension the depth map).
        /// Values below the given threshold are removed from the depth map.
        /// 获取视差图(以及扩展的深度图)的当前置信度阈值。
        /// 低于给定阈值的值将从深度图中删除。
        /// 
        /// Filtering value between 0 and 100.
        public int GetConfidenceThreshold()
        {
            return dllz_get_confidence_threshold(CameraID);
        }

        /// 
        /// Gets the timestamp at the time the latest grabbed frame was extracted from the USB stream.
        /// This is the closest timestamp you can get from when the image was taken. Must be called after calling grab().
        /// 获取从USB流中提取最新抓取的帧时的时间戳。
        /// 这是您拍摄图像时可获得的最接近的时间戳。必须在调用grab()之后调用。
        /// 
        /// Current timestamp in nanoseconds. -1 means it's is not available, such as with an .SVO file without compression.
        /// 当前时间戳(以纳秒为单位)。 -1表示它不可用,例如未压缩的.SVO文件。
        public ulong GetCameraTimeStamp()
        {
            return dllz_get_camera_timestamp(CameraID);
        }

        /// 
        /// Gets the current timestamp at the time the function is called. Can be compared to the camera timestamp
        /// for synchronization, since they have the same reference (the computer's start time).
        /// 获取调用该函数时的当前时间戳。可以与相机时间戳
        /// 进行比较,因为它们具有相同的参考(计算机的开始时间)。  时间单位是纳秒
        /// 
        /// The timestamp in nanoseconds.
        public ulong GetCurrentTimeStamp()
        {
            return dllz_get_current_timestamp(CameraID);
        }

        /// 
        /// Timestamp from the most recent image update. Based on the computer's start time.
        /// 最近一次图像更新的时间戳。基于计算机的启动时间。
        /// 
        /// The timestamp in nanoseconds.
        public ulong GetImageUpdaterTimeStamp()
        {
            return dllz_get_image_updater_time_stamp(CameraID);
        }

        /// 
        /// Get the current position of the SVO being recorded to.
        /// 获取SVO文件当前的位置,这个位置是要用来录制的。
        /// 
        /// Index of the frame being recorded to.
        public int GetSVOPosition()
        {
            return dllz_get_svo_position(CameraID);
        }

        /// 
        /// Gets the total number of frames in the loaded SVO file.
        /// 获取已加载的SVO文件中的帧总数。
        /// 
        /// Total frames in the SVO file. Returns -1 if the SDK is not reading an SVO.
        public int GetSVONumberOfFrames()
        {
            return dllz_get_svo_number_of_frames(CameraID);
        }

        /// 
        /// Gets the closest measurable distance by the camera, according to the camera type and depth map parameters.
        /// 根据摄像机类型和深度图参数,获取摄像机最近的可测量距离。
        /// 
        /// The nearest possible depth value.
        public float GetDepthMinRangeValue()
        {
            return dllz_get_depth_min_range_value(CameraID);
        }

        /// 
        /// Returns the current maximum distance of depth/disparity estimation.
        /// 返回深度/视差估计的当前最大距离。
        /// 
        /// The closest depth
        public float GetDepthMaxRangeValue()
        {
            return dllz_get_depth_max_range_value(CameraID);
        }

        /// 
        /// Initialize and Start the tracking functions
        /// 初始化并启动跟踪功能
        /// 
        ///  rotation used as initial world transform. By default it should be identity.初始化相机的时候的变换。默认情况下,它是确定的。
        ///  translation used as initial world transform. By default it should be identity.初始化相机的时候的位置,默认情况下,它是确定的
        ///   (optional) define if spatial memory is enable or not.空间映射数据内存是否需要(可选)
        ///  (optional) file of spatial memory file that has to be loaded to relocate in the scene.(可选)必须加载才能在场景中重新定位的空间存储文件的文件。
        /// 
        public sl.ERROR_CODE EnableTracking(ref Quaternion quat, ref Vector3 vec, bool enableSpatialMemory = true,
            bool enablePoseSmoothing = false, bool enableFloorAlignment = false, bool trackingIsStatic = false,
            bool enableIMUFusion = true, string areaFilePath = "")
        {
            sl.ERROR_CODE trackingStatus = sl.ERROR_CODE.CAMERA_NOT_DETECTED;
            trackingStatus = (sl.ERROR_CODE) dllz_enable_tracking(CameraID, ref quat, ref vec, enableSpatialMemory,
                enablePoseSmoothing, enableFloorAlignment,
                trackingIsStatic, enableIMUFusion, new System.Text.StringBuilder(areaFilePath, areaFilePath.Length));
            return trackingStatus;
        }

        /// 
        /// Reset tracking
        /// 重置跟踪
        /// 
        /// 
        /// 
        /// 
        public sl.ERROR_CODE ResetTracking(Quaternion rotation, Vector3 translation)
        {
            sl.ERROR_CODE trackingStatus = sl.ERROR_CODE.CAMERA_NOT_DETECTED;
            trackingStatus = (sl.ERROR_CODE) dllz_reset_tracking(CameraID, rotation, translation);
            return trackingStatus;
        }

        /// 
        /// 重置追踪,但是附带有偏移量
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public sl.ERROR_CODE ResetTrackingWithOffset(Quaternion rotation, Vector3 translation,
            Quaternion rotationOffset, Vector3 translationOffset)
        {
            sl.ERROR_CODE trackingStatus = sl.ERROR_CODE.CAMERA_NOT_DETECTED;
            trackingStatus = (sl.ERROR_CODE) dllz_reset_tracking_with_offset(CameraID, rotation, translation,
                rotationOffset, translationOffset);
            return trackingStatus;
        }

        /// 
        /// 计算初始的位置
        /// 
        /// 
        /// 
        /// 
        public sl.ERROR_CODE EstimateInitialPosition(ref Quaternion rotation, ref Vector3 translation)
        {
            sl.ERROR_CODE status = sl.ERROR_CODE.CAMERA_NOT_DETECTED;
            status = (sl.ERROR_CODE) dllz_estimate_initial_position(CameraID, ref rotation, ref translation, 2, 100);
            return status;
        }


        /// 
        ///  取消追踪的功能
        /// 
        /// The path to save the area file
        public void DisableTracking(string path = "")
        {
            dllz_disable_tracking(CameraID, new System.Text.StringBuilder(path, path.Length));
        }

        /// 
        /// 保存当前的区域,这个应该是用于保存depth  map的特征点才对,还得进一步确认
        /// 
        /// 
        /// 
        public sl.ERROR_CODE SaveCurrentArea(string path)
        {
            return (sl.ERROR_CODE) dllz_save_current_area(CameraID, new System.Text.StringBuilder(path, path.Length));
        }

        /// 
        /// Returns the current state of the area learning saving
        /// 返回区域学习保存的状态
        /// 
        /// 
        public sl.AREA_EXPORT_STATE GetAreaExportState()
        {
            return (sl.AREA_EXPORT_STATE) dllz_get_area_export_state(CameraID);
        }

        /// 
        /// Register a texture to the base
        /// 注册一个基本的纹理
        /// 
        private void RegisterTexture(Texture2D m_Texture, int type, int mode)
        {
            TextureRequested t = new TextureRequested();

            t.type = type; // 纹理类型
            t.option = mode; // 纹理选项
            texturesRequested.Add(t); //把纹理添加到列表里面
            textures[type].Add(mode, m_Texture); //添加到纹理字典里面
        }

        /// 
        /// Creates or retrieves a texture of type Image. Will be updated each frame automatically.
        /// 创建或获取图像类型的纹理。将自动更新每帧。
        /// Lance:其实就是我们常说的RGB图片而已
        /// Image type textures are human-viewable, but have less accuracy than measure types.
        /// 图像类型的纹理是人类可见的,但其精度低于度量类型。
        /// 
        /// 
        /// Note that the new texture will exist on the GPU, so accessing from the CPU will result in an empty image. To get images
        /// with the CPU, use RetrieveImage() instead and specify CPU memory in the arguments.
        /// 请注意,新纹理将存在于GPU上,因此从CPU进行访问图像的结果是为空的。
        /// 要使用CPU获取图像,请改用RetrieveImage()并在参数中指定CPU内存。
        /// 
        /// What the image shows (left RGB image, right depth image, normal map, etc.)
        /// 图像显示的内容(左RGB图像,右深度图像,法线贴图等)
        /// /// Resolution of the image. Should correspond to ZED's current resolution.
        /// 图像分辨率。应符合ZED当前的分辨率。
        /// Texture2D that will update each frame with the ZED SDK's output.
        /// Texture2D将使用ZED SDK的输出更新每个帧。
        public Texture2D CreateTextureImageType(VIEW mode, Resolution resolution = new Resolution())
        {
            if (HasTexture((int) TYPE_VIEW.RETRIEVE_IMAGE, (int) mode))
            {
                return textures[(int) TYPE_VIEW.RETRIEVE_IMAGE][(int) mode];
            }

            if (!cameraReady)
                return null;

            int width = ImageWidth;
            int height = imageHeight;
            if (!((uint) resolution.width == 0 && (uint) resolution.height == 0)
            ) //Handles if Resolution arg was empty, as in the default.
            {
                width = (int) resolution.width;
                height = (int) resolution.height;
            }

            Texture2D m_Texture;
            if (mode == VIEW.LEFT_GREY || mode == VIEW.RIGHT_GREY || mode == VIEW.LEFT_UNRECTIFIED_GREY ||
                mode == VIEW.RIGHT_UNRECTIFIED_GREY)
            {
                m_Texture = new Texture2D(width, height, TextureFormat.Alpha8, false);
            }
            else if (mode == VIEW.SIDE_BY_SIDE)
            {
                m_Texture = new Texture2D(width * 2, height, TextureFormat.RGBA32,
                    false); //Needs to be twice as wide for SBS because there are two images.
            }
            else
            {
                m_Texture = new Texture2D(width, height, TextureFormat.RGBA32, false);
            }

            m_Texture.filterMode = FilterMode.Point;
            m_Texture.wrapMode = TextureWrapMode.Clamp;

            m_Texture.Apply();

            IntPtr idTexture = m_Texture.GetNativeTexturePtr();
            int error = dllz_register_texture_image_type(CameraID, (int) mode, idTexture, resolution);
            if (error != 0)
            {
                throw new Exception("CUDA error:" + error +
                                    " if the problem appears again, please contact Stereolabs support.");
            }

            if (!textures.ContainsKey((int) TYPE_VIEW.RETRIEVE_IMAGE))
            {
                textures.Add((int) TYPE_VIEW.RETRIEVE_IMAGE, new Dictionary<int, Texture2D>());
            }

            RegisterTexture(m_Texture, (int) TYPE_VIEW.RETRIEVE_IMAGE,
                (int) mode); //Save so you don't make a duplicate if another script needs the texture.

            return m_Texture;
        }

        /// 
        /// Creates or retrievse a texture of type Measure. Will be updated each frame automatically.
        /// Measure types are not human-viewable, but don't lose any accuracy.
        /// 创建或检索Measure类型的纹理。将自动更新每帧。
        /// 度量类型不是人类可见的,但不会失去任何准确性。
        /// Lance:这边的度量类型我一直不理解是什么类型,我估计是深度图的意思
        /// 
        /// 
        /// Note that the new texture will exist on the GPU, so accessing from the CPU will result in an empty image. To get images
        /// with the CPU, use RetrieveMeasure() instead and specify CPU memory in the arguments.
        /// 请注意,新纹理将存在于GPU上,因此从CPU进行访问的化返回结果将为空。
        /// 要使用CPU获取图像,请改用RetrieveMeasure()并在参数中指定CPU内存。
        /// 
        /// What the image shows (disparity, depth, confidence, etc.),图像显示的内容(视差,深度,置信度等)
        /// Resolution of the image. Should correspond to ZED's current resolution.图像分辨率。应符合ZED当前的分辨率。
        /// Texture2D that will update each frame with the ZED SDK's output.Texture2D将使用ZED SDK的输出更新每个帧。
        /// Lance: 这个measure类型的纹理确定就是深度图像,只是模式不同的话,返回的数据类型不同。
        public Texture2D CreateTextureMeasureType(MEASURE mode, Resolution resolution = new Resolution())
        {
            if (HasTexture((int) TYPE_VIEW.RETRIEVE_MEASURE, (int) mode))
            {
                return textures[(int) TYPE_VIEW.RETRIEVE_MEASURE][(int) mode];
            }

            if (!cameraReady)
                return null;

            Texture2D m_Texture;
            int width = ImageWidth;
            int height = imageHeight;
            if (!((uint) resolution.width == 0 && (uint) resolution.height == 0))
            {
                width = (int) resolution.width;
                height = (int) resolution.height;
            }

            //Handle the mode options.
            //不同的数据组织类型,
            if (mode == MEASURE.XYZ || mode == MEASURE.XYZABGR || mode == MEASURE.XYZARGB || mode == MEASURE.XYZBGRA ||
                mode == MEASURE.XYZRGBA || mode == MEASURE.NORMALS
                || mode == MEASURE.XYZ_RIGHT || mode == MEASURE.XYZABGR_RIGHT || mode == MEASURE.XYZARGB_RIGHT ||
                mode == MEASURE.XYZBGRA_RIGHT || mode == MEASURE.XYZRGBA_RIGHT || mode == MEASURE.NORMALS_RIGHT)
            {
                //这边的类型就是点云的类型,XYZ
                m_Texture = new Texture2D(width, height, TextureFormat.RGBAFloat, false, true); //实例化相应的纹理以准备接收相应的纹理数据
            }
            else if (mode == MEASURE.DEPTH || mode == MEASURE.CONFIDENCE || mode == MEASURE.DISPARITY ||
                     mode == MEASURE.DEPTH_RIGHT || mode == MEASURE.DISPARITY_RIGHT)
            {
                // 这边的类型是深度图像的类型
                m_Texture = new Texture2D(width, height, TextureFormat.RFloat, false, true);
            }
            else
            {
                //这边的类型是彩色图像的类型
                m_Texture = new Texture2D(width, height, TextureFormat.RGBA32, false, true);
            }

            if (!((uint) resolution.width == 0 && (uint) resolution.height == 0)) //确定设置了分辨率
            {
                m_Texture.filterMode = FilterMode.Bilinear; //双向线性滤波器
            }
            else
            {
                m_Texture.filterMode = FilterMode.Point; //点滤波器  这又是啥滤波器
            }

            m_Texture.wrapMode = TextureWrapMode.Clamp; // 包装的模式为堆类型  这个还不是很懂
            m_Texture.Apply(); //应用设置的这些参数

            IntPtr idTexture = m_Texture.GetNativeTexturePtr(); //纹理的ID号  这个是什么鬼

            int error = dllz_register_texture_measure_type(CameraID, (int) mode, idTexture, resolution); //告诉底层抓取新的数据

            if (error != 0) //如果错误
            {
                throw new Exception("CUDA error:" + error +
                                    " if the problem appears again, please contact Stereolabs support.");
            }

            if (!textures.ContainsKey((int) TYPE_VIEW.RETRIEVE_MEASURE)) //如果没有包括这个键值
            {
                textures.Add((int) TYPE_VIEW.RETRIEVE_MEASURE, new Dictionary<int, Texture2D>()); //新添加这个键值对
            }

            RegisterTexture(m_Texture, (int) TYPE_VIEW.RETRIEVE_MEASURE,
                (int) mode); //Save to avoid duplicates if texture type is needed elsewhere.
            // 如果在其他位置需要纹理类型,请保存以免重复。
            // Lance:就是说 如果需要需要点云数据 或者深度图像的话  在调用这个函数后,应该从 textures这个纹理字典中获得

            return m_Texture;
        }

        /// 
        /// Unregisters a texture of type Image. The texture will be destroyed and will no longer be updated each frame.
        /// 注销图像类型的纹理。纹理将被破坏,并且将不再在每一帧进行更新。
        /// 
        /// What the image was showing (left RGB image, right depth image, normal map, etc.)
        /// 图像显示的内容(左RGB图像,右深度图像,法线贴图等)
        public bool UnregisterTextureImageType(sl.VIEW view)
        {
            DestroyTextureImageType((int) view);
            return dllz_unregister_texture_image_type(CameraID, (int) view) != 0;
        }

        /// 
        /// Unregisters a texture of type Measure, The texture will be destroyed and will no longer be updated each frame.
        /// 取消注册Measure类型的纹理,该纹理将被销毁,并且不再在每个帧中更新。
        /// 
        /// What the measure was showing (disparity, depth, confidence, etc.),度量显示的内容(差异,深度,置信度等)
        public bool UnregisterTextureMeasureType(sl.MEASURE measure)
        {
            DestroyTextureMeasureType((int) measure);
            return dllz_unregister_texture_measure_type(CameraID, (int) measure) != 0;
        }

        /// 
        /// Copies a Texture of type Image into a ZEDMat. This function should be called after a Grab() and an UpdateTextures().
        /// 将Image类型的Texture复制到ZEDMat中。该函数应在Grab()和UpdateTextures()之后调用。
        /// Lance:也就是说当我们需要以矩阵的形式获得彩色图片数据、深度图像需要调用这个函数
        /// 
        /// View type (left rgb, right depth, etc.)
        /// New ZEDMat for an image texture of the selected view type.就是返回相应的图像矩阵ZEDMat。
        public ZEDMat RequestCopyMatFromTextureImageType(sl.VIEW view)
        {
            return new ZEDMat(dllz_get_copy_mat_texture_image_type(CameraID, (int) view));
        }

        /// 
        /// Copies a texture of type Measure into a ZEDMat. This function should be called after a Grab() and an UpdateTextures().
        /// 将“Measure”类型的纹理复制到ZEDMat中。该函数应在Grab()和UpdateTextures()之后调用。
        /// 
        /// Measure type (depth, disparity, confidence, etc.),度量类型(深度,差异,置信度等)
        /// New ZEDMat for a measure texture of the selected measure type.相应的数据矩阵
        public ZEDMat RequestCopyMatFromTextureMeasureType(sl.MEASURE measure)
        {
            return new ZEDMat(dllz_get_copy_mat_texture_measure_type(CameraID, (int) measure));
        }

        /// 
        /// Destroys a texture and removes its reference in the textures list.
        /// 销毁纹理并在纹理列表中删除其参考。
        /// 
        /// Type of texture as an int (0 for Image, 1 for Measure).纹理的类型(整数)(0表示图像,1表示测量类型)。
        /// Corresponding options enum (sl.VIEW if Image type, sl.MEASURE if Measure type) as an integer.
        /// 对应的选项枚举(如果是图像类型,则为sl.VIEW;如果是度量类型,则为sl.MEASURE),以整数形式表示。
        private void DestroyTexture(int type, int option)
        {
            if (textures.ContainsKey(type) && textures[type].ContainsKey(option))
            {
                textures[type][option] = null;
                textures[type].Remove(option);
                if (textures[type].Count == 0)
                {
                    textures.Remove(type);
                }
            }
        }

        /// 
        /// Destroy all textures that were ever requested.
        /// 销毁所有需要的纹理。
        /// 
        private void DestroyAllTexture()
        {
            if (cameraReady)
            {
                foreach (TextureRequested t in texturesRequested)
                {
                    DestroyTexture(t.type, t.option);
                }

                texturesRequested.Clear();
            }
        }


        /// 
        /// Destroy a texture created with CreateTextureImageType().
        /// 销毁使用CreateTextureImageType()创建的某个纹理。
        /// 
        /// View type (left RGB, right depth image, etc.) as an integer.
        /// 视图类型(左RGB,右深度图像等)为整数。
        private void DestroyTextureImageType(int option)
        {
            DestroyTexture((int) TYPE_VIEW.RETRIEVE_IMAGE, option);
        }

        /// 
        /// Destroy a texture created with CreateTextureMeasureType().
        /// 销毁使用CreateTextureMeasureType()创建的某个纹理。
        /// 
        /// Measure type (depth, confidence, etc.) as an integer.
        /// 度量类型(深度,置信度等)为整数。
        private void DestroyTextureMeasureType(int option)
        {
            DestroyTexture((int) TYPE_VIEW.RETRIEVE_MEASURE, option);
        }

        /// 
        /// Retrieves a texture that was already created.
        /// 检索已经创建的纹理。
        /// 
        /// Type of texture as an integer (0 for Image, 1 for Measure).
        /// 纹理类型,为整数(对于图像为0,对于度量为1)。
        /// Corresponding options enum (sl.VIEW if Image type, sl.MEASURE if Measure type) as an integer.
        /// 对应的选项枚举(如果是图像类型,则为sl.VIEW;如果是度量类型,则为sl.MEASURE),以整数形式表示。
        /// Existing texture of the given type/mode.
        public Texture2D GetTexture(TYPE_VIEW type, int mode)
        {
            if (HasTexture((int) type, mode))
            {
                return textures[(int) type][mode];
            }

            return null;
        }

        /// 
        /// Checks if a texture of a given type has already been created.
        /// 检查是否已创建给定类型的纹理。
        /// 
        /// Type of texture as an integer (0 for Image, 1 for Measure).
        /// Corresponding options enum (sl.VIEW if Image type, sl.MEASURE if Measure type) as an integer.
        /// True if the texture is available.
        private bool HasTexture(int type, int mode)
        {
            if (cameraReady) //Texture can't exist if the ZED hasn't been initialized yet.
            {
                return textures.ContainsKey((int) type) && textures[type].ContainsKey((int) mode);
            }

            return false;
        }

        /// 
        /// Returns the current camera FPS. This is limited primarily by resolution but can also be lower due to
        /// setting a lower desired resolution in Init() or from USB connection/bandwidth issues.
        /// 返回当前相机的FPS。这主要受分辨率限制,但由于///在Init()中设置了较低的所需分辨率,或者由于USB连接/带宽问题,也可能较低。
        /// 
        /// The current fps,当前帧率
        public float GetCameraFPS()
        {
            return dllz_get_camera_fps(CameraID);
        }

        /// 
        /// 获得相机的标定参数
        /// 
        /// 是否是原始图像,原始图像为未矫正畸变的图像
        /// 
        public CalibrationParameters GetCalibrationParameters(bool raw = false)
        {
            IntPtr p = dllz_get_calibration_parameters(CameraID, raw);

            if (p == IntPtr.Zero)
            {
                return new CalibrationParameters();
            }

            CalibrationParameters parameters =
                (CalibrationParameters) Marshal.PtrToStructure(p, typeof(CalibrationParameters));

            if (raw)
                calibrationParametersRaw = parameters; //未矫正畸变的图像参数
            else
                calibrationParametersRectified = parameters; //畸变矫正过的图像参数


            return parameters;
        }

        /// 
        /// Gets the ZED camera model (ZED or ZED Mini).
        /// 获得相机的型号
        /// 
        /// Model of the ZED as sl.MODEL.
        public sl.MODEL GetCameraModel()
        {
            return (sl.MODEL) dllz_get_camera_model(CameraID);
        }

        /// 
        /// Gets the ZED's camera firmware version.
        /// 获取ZED的相机固件版本。
        /// 
        /// Firmware version.
        public int GetCameraFirmwareVersion()
        {
            return dllz_get_camera_firmware(CameraID);
        }

        /// 
        /// Gets the ZED's sensors firmware version.
        /// 获取ZED的传感器固件版本。
        /// 
        /// Firmware version.
        public int GetSensorsFirmwareVersion()
        {
            return dllz_get_sensors_firmware(CameraID);
        }

        /// 
        /// Gets the ZED's serial number.
        /// 获取ZED的串口号。
        /// 
        /// Serial number
        public int GetZEDSerialNumber()
        {
            return dllz_get_zed_serial(CameraID);
        }

        /// 
        /// Returns the ZED's vertical field of view in radians.
        /// 以弧度返回ZED的垂直视场。
        /// 
        /// Vertical field of view.
        public float GetFOV()
        {
            return GetCalibrationParameters(false).leftCam.vFOV * Mathf.Deg2Rad;
        }


        /// 
        /// Computes textures from the ZED. The new textures will not be displayed until an event is sent to the render thread.
        /// This event is called from UpdateTextures().
        /// 从ZEDz注册纹理。在将事件发送到渲染线程之前,不会显示新纹理。
        /// ///从UpdateTextures()调用此事件。
        /// 
        public void RetrieveTextures()
        {
            dllz_retrieve_textures(CameraID);
        }

        /// 
        /// Swaps textures safely between the acquisition and rendering threads.
        /// 在采集和渲染线程之间安全地交换纹理。
        /// 
        public void SwapTextures()
        {
            dllz_swap_textures(CameraID);
        }

        /// 
        /// Timestamp of the images used the last time the ZED wrapper updated textures.
        /// 上一次ZED包装器更新纹理时使用的图像时间戳。
        /// 
        /// 
        public ulong GetImagesTimeStamp()
        {
            return dllz_get_updated_textures_timestamp(CameraID);
        }

        /// 
        /// Gets the number of frames dropped since Grab() was called for the first time.
        /// Based on camera timestamps and an FPS comparison.
        /// 获取自首次调用Grab()以来丢弃的帧数。
        /// 基于相机时间戳和FPS比较。
        /// Similar to the Frame Drop display in the ZED Explorer app.
        /// 类似于ZED Explorer应用程序中的“丢帧”显示。
        /// Frames dropped since first Grab() call.
        /// 自从第一次Grab()调用以来,丢掉的帧数。
        public uint GetFrameDroppedCount()
        {
            return dllz_get_frame_dropped_count(CameraID);
        }

        /// 
        /// Gets the percentage of frames dropped since Grab() was called for the first time.
        /// 获取自首次调用Grab()以来丢弃的帧的百分比。
        /// 
        /// Percentage of frames dropped.
        public float GetFrameDroppedPercent()
        {
            return dllz_get_frame_dropped_percent(CameraID);
        }

        /// 
        /// Gets the position of the camera and the current state of the ZED Tracking.
        /// 获取摄像机的位置和ZED跟踪的当前状态。
        /// Lance:这个函数可能在之后的hololens开发中需要用到,用于两者的空间匹配
        /// 
        /// Quaternion filled with the current rotation of the camera depending on its reference frame.
        /// 相机旋转的四元数(已赋值),其值具体取决于摄像机的参考系。
        /// Vector filled with the current position of the camera depending on its reference frame.
        /// 根据摄像机的参考帧填充摄像机当前位置的矢量
        /// Reference frame for setting the rotation/position. CAMERA gives movement relative to the last pose.
        /// WORLD gives cumulative movements since tracking started.
        /// 用于设置旋转/位置的参考框架。相机给出相对于最后姿势的运动。
        /// WORLD自跟踪开始以来提供累计移动。
        /// State of ZED's Tracking system (off, searching, ok).
        public TRACKING_STATE GetPosition(ref Quaternion rotation, ref Vector3 position,
            REFERENCE_FRAME referenceType = REFERENCE_FRAME.WORLD)
        {
            return (TRACKING_STATE) dllz_get_position(CameraID, ref rotation, ref position, (int) referenceType);
        }

        /// 
        /// Gets the current position of the camera and state of the tracking, with an optional offset to the tracking frame.
        /// 获取摄像头的当前位置和跟踪状态,以及跟踪框的可选偏移量。
        /// 
        /// Quaternion filled with the current rotation of the camera depending on its reference frame.
        /// Vector filled with the current position of the camera depending on its reference frame.
        /// Rotational offset applied to the tracking frame.
        /// Positional offset applied to the tracking frame.
        /// Reference frame for setting the rotation/position. CAMERA gives movement relative to the last pose.
        /// WORLD gives cumulative movements since tracking started.
        /// State of ZED's Tracking system (off, searching, ok).
        public TRACKING_STATE GetPosition(ref Quaternion rotation, ref Vector3 translation,
            ref Quaternion targetQuaternion, ref Vector3 targetTranslation,
            REFERENCE_FRAME referenceFrame = REFERENCE_FRAME.WORLD)
        {
            return (TRACKING_STATE) dllz_get_position_at_target_frame(CameraID, ref rotation, ref translation,
                ref targetQuaternion, ref targetTranslation, (int) referenceFrame);
        }


        /// 
        /// Gets the current position of the camera and state of the tracking, with a defined tracking frame.
        /// A tracking frame defines what part of the ZED is its center for tracking purposes. See ZEDCommon.TRACKING_FRAME.
        /// 使用定义的跟踪frame,获取摄像机的当前位置和跟踪状态。
        /// 跟踪frame定义ZED的哪一部分是其中心以进行跟踪。参见ZEDCommon.TRACKING_FRAME。
        /// 
        /// Quaternion filled with the current rotation of the camera depending on its reference frame.
        /// Vector filled with the current position of the camera depending on its reference frame.
        /// Center of the ZED for tracking purposes (left eye, center, right eye).
        /// Reference frame for setting the rotation/position. CAMERA gives movement relative to the last pose.
        /// WORLD gives cumulative movements since tracking started.
        /// State of ZED's Tracking system (off, searching, ok).
        public TRACKING_STATE GetPosition(ref Quaternion rotation, ref Vector3 translation,
            TRACKING_FRAME trackingFrame, REFERENCE_FRAME referenceFrame = REFERENCE_FRAME.WORLD)
        {
            Quaternion rotationOffset = Quaternion.identity;
            Vector3 positionOffset = Vector3.zero;
            switch (trackingFrame) //Add offsets to account for different tracking frames.
            {
                case sl.TRACKING_FRAME.LEFT_EYE:
                    positionOffset = new Vector3(0, 0, 0);
                    break;
                case sl.TRACKING_FRAME.RIGHT_EYE:
                    positionOffset = new Vector3(Baseline, 0, 0);
                    break;
                case sl.TRACKING_FRAME.CENTER_EYE:
                    positionOffset = new Vector3(Baseline / 2.0f, 0, 0);
                    break;
            }

            return (TRACKING_STATE) dllz_get_position_at_target_frame(CameraID, ref rotation, ref translation,
                ref rotationOffset, ref positionOffset, (int) referenceFrame);
        }

        /// 
        /// Gets the current position of the camera and state of the tracking, filling a Pose struct useful for AR pass-through.
        /// 获取摄像头的当前位置和跟踪状态,填充对AR有用的Pose结构体。
        /// 
        /// Current pose.
        /// Reference frame for setting the rotation/position. CAMERA gives movement relative to the last pose.
        /// WORLD gives cumulative movements since tracking started.
        /// State of ZED's Tracking system (off, searching, ok).
        public TRACKING_STATE GetPosition(ref Pose pose, REFERENCE_FRAME referenceType = REFERENCE_FRAME.WORLD)
        {
            return (TRACKING_STATE) dllz_get_position_data(CameraID, ref pose, (int) referenceType);
        }


        /// 
        /// Sets a prior to the IMU orientation (only for ZED-M).
        /// Prior must come from a external IMU, such as the HMD orientation and should be in a time frame
        /// that's as close as possible to the camera.
        /// 将IMU方向设置为先(仅适用于ZED-M)。
        /// 先验必须来自外部IMU,例如HMD方向,
        /// 并且应位于与摄像机尽可能近的时间范围内
        /// Lance:不是很确定这是个什么东西
        /// 
        /// Error code status.
        /// Prior rotation.
        public ERROR_CODE SetIMUOrientationPrior(ref Quaternion rotation)
        {
            sl.ERROR_CODE trackingStatus = sl.ERROR_CODE.CAMERA_NOT_DETECTED;
            trackingStatus = (sl.ERROR_CODE) dllz_set_imu_prior_orientation(CameraID, rotation);
            return trackingStatus;
        }

        /// 
        /// Gets the rotation given by the ZED-M/ZED2 IMU. Return an error if using ZED (v1) which does not contains internal sensors
        /// 获取ZED-M / ZED2 IMU给出的旋转角度。
        /// 如果使用不包含内部传感器的ZED(v1),则返回错误
        /// Lance:想要获取相机内部的IMU数据的话得调用这个函数
        /// 
        /// Error code status.
        /// Rotation from the IMU.
        public ERROR_CODE GetInternalIMUOrientation(ref Quaternion rotation,
            TIME_REFERENCE referenceTime = TIME_REFERENCE.IMAGE)
        {
            sl.ERROR_CODE err = sl.ERROR_CODE.CAMERA_NOT_DETECTED;
            err = (sl.ERROR_CODE) dllz_get_internal_imu_orientation(CameraID, ref rotation, (int) referenceTime);
            return err;
        }

        /// 
        /// Gets the full Sensor data from the ZED-M or ZED2 . Return an error if using ZED (v1) which does not contains internal sensors
        /// 从ZED-M或ZED2获取完整的传感器数据。如果使用不包含内部传感器的ZED(v1),则返回错误
        /// 
        /// Error code status.
        /// Rotation from the IMU.
        public ERROR_CODE GetInternalSensorsData(ref SensorsData data,
            TIME_REFERENCE referenceTime = TIME_REFERENCE.IMAGE)
        {
            sl.ERROR_CODE err = sl.ERROR_CODE.CAMERA_NOT_DETECTED;
            err = (sl.ERROR_CODE) dllz_get_internal_sensors_data(CameraID, ref data, (int) referenceTime);
            return err;
        }

        /// 
        /// Converts a float array to a matrix.
        /// 将float数组转换为矩阵。
        /// 
        /// Matrix to be filled.
        /// Float array to be turned into a matrix.
        static public void
            Float2Matrix(ref Matrix4x4 m, float[] f) //因为传入的是指针,所以不需要范围,直接修改是相应内存的参数,外部需要访问这个矩阵的话,只需要有相应的指针就可以
        {
            if (f == null) return;
            if (f.Length != 16) return;
            for (int i = 0; i < 4; ++i)
            {
                for (int j = 0; j < 4; ++j)
                {
                    m[i, j] = f[i * 4 + j];
                }
            }
        }

        /// 
        /// Sets a value in the ZED's camera settings.
        /// 在ZED的相机设置中设置一个值。
        /// 
        /// Setting to be changed (brightness, contrast, gain, exposure, etc.),要更改的设置(亮度,对比度,增益,曝光等)
        /// New value.
        /// True to set the settings to their default values.如果为True,则将设置设为默认值。
        public void SetCameraSettings(CAMERA_SETTINGS settings, int value)
        {
            AssertCameraIsReady();
            //cameraSettingsManager.SetCameraSettings(CameraID, settings, value);
            dllz_set_video_settings(CameraID, (int) settings, value);
        }

        /// 
        /// Gets the value of a given setting from the ZED camera.
        /// 从ZED摄像机获取给定设置的值。
        /// 
        /// Setting to be retrieved (brightness, contrast, gain, exposure, etc.)
        public int GetCameraSettings(CAMERA_SETTINGS settings)
        {
            AssertCameraIsReady();
            return dllz_get_video_settings(CameraID, (int) settings);
            //return cameraSettingsManager.GetCameraSettings(CameraID, settings);
        }

        /// 
        /// Overloaded function for CAMERA_SETTINGS.AEC_AGC_ROI (requires iRect as input)
        /// CAMERA_SETTINGS.AEC_AGC_ROI的重载函数(需要iRect作为输入)
        /// Lance: roi 是什么玩意
        /// 
        ///  Must be set to CAMERA_SETTINGS.AEC_AGC_ROI. Otherwise will return -1.
        ///  defines left=0 or right=1 or both=2 sensor target
        /// the roi defined as a sl.Rect
        /// Defines if the target must be reset to full sensor
        /// 
        public int SetCameraSettings(CAMERA_SETTINGS settings, int side, iRect roi, bool reset)
        {
            AssertCameraIsReady();
            if (settings == CAMERA_SETTINGS.AEC_AGC_ROI)
                return dllz_set_roi_for_aec_agc(CameraID, side, roi, reset);
            else
                return -1;
        }

        /// 
        /// Overloaded function for CAMERA_SETTINGS.AEC_AGC_ROI (requires iRect as input)
        /// CAMERA_SETTINGS.AEC_AGC_ROI的重载函数(需要iRect作为输入)
        /// 
        ///  Must be set to CAMERA_SETTINGS.AEC_AGC_ROI. Otherwise will return -1.
        ///  defines left=0 or right=1 or both=2 sensor target.
        ///  Roi that will be filled.
        /// 
        public int GetCameraSettings(CAMERA_SETTINGS settings, int side, ref iRect roi)
        {
            AssertCameraIsReady();
            if (settings == CAMERA_SETTINGS.AEC_AGC_ROI)
                return dllz_get_roi_for_aec_agc(CameraID, side, ref roi);
            else
                return -1;
        }

        /// 
        /// Reset camera settings to default
        /// 将相机设置重置为默认设置
        /// 
        public void ResetCameraSettings()
        {
            AssertCameraIsReady();
            //cameraSettingsManager.ResetCameraSettings(this);

            SetCameraSettings(sl.CAMERA_SETTINGS.BRIGHTNESS, sl.ZEDCamera.brightnessDefault);
            SetCameraSettings(sl.CAMERA_SETTINGS.CONTRAST, sl.ZEDCamera.contrastDefault);
            SetCameraSettings(sl.CAMERA_SETTINGS.HUE, sl.ZEDCamera.hueDefault);
            SetCameraSettings(sl.CAMERA_SETTINGS.SATURATION, sl.ZEDCamera.saturationDefault);
            SetCameraSettings(sl.CAMERA_SETTINGS.SHARPNESS, sl.ZEDCamera.sharpnessDefault);
            SetCameraSettings(sl.CAMERA_SETTINGS.GAMMA, sl.ZEDCamera.gammaDefault);
            SetCameraSettings(sl.CAMERA_SETTINGS.AUTO_WHITEBALANCE, 1);
            SetCameraSettings(sl.CAMERA_SETTINGS.AEC_AGC, 1);
            SetCameraSettings(sl.CAMERA_SETTINGS.LED_STATUS, 1);

            SetCameraSettings(sl.CAMERA_SETTINGS.AEC_AGC_ROI, 2, new sl.iRect(), true);
        }

        /// 
        /// Loads camera settings (brightness, contrast, hue, saturation, gain, exposure) from a file in the
        /// project's root directory.
        /// 从项目根目录中的文件加载相机设置(亮度,对比度,色调,饱和度,增益,曝光)。
        /// 
        /// Filename.
        public void LoadCameraSettings(string path)
        {
            cameraSettingsManager.LoadCameraSettings(this, path);
        }

        /// 
        /// Save the camera settings (brightness, contrast, hue, saturation, gain, exposure) to a file
        /// relative to the project's root directory.
        /// 将相机设置(亮度,对比度,色调,饱和度,增益,曝光)保存到文件
        /// 相对于项目根目录。
        /// 
        /// Filename.
        public void SaveCameraSettings(string path)
        {
            cameraSettingsManager.SaveCameraSettings(path);
        }

        /// 
        /// Retrieves camera settings from the ZED camera and loads them into a CameraSettings instance
        /// handled by ZEDCameraSettingsManager.
        /// 从ZED摄像机检索摄像机设置,并将其加载到由ZEDCameraSettingsManager处理的CameraSettings实例中。
        /// 
        public void RetrieveCameraSettings()
        {
            cameraSettingsManager.RetrieveSettingsCamera(this);
        }

        /// 
        /// Returns if the camera's exposure mode is set to automatic.
        /// 如果相机的曝光模式设置为自动,则返回。
        /// 
        /// True if automatic, false if manual.
        public bool GetExposureUpdateType()
        {
            return cameraSettingsManager.auto;
        }

        /// 
        /// Returns if the camera's white balance  is set to automatic.
        /// 如果相机的白平衡设置为自动,则返回。
        /// 
        /// True if automatic, false if manual.
        public bool GetWhiteBalanceUpdateType()
        {
            return cameraSettingsManager.whiteBalanceAuto;
        }

        /// 
        /// Applies all the settings registered in the ZEDCameraSettingsManager instance to the actual ZED camera.
        /// 将在ZEDCameraSettingsManager实例中注册的所有设置应用于实际的ZED摄像机。
        /// 
        public void SetCameraSettings()
        {
            cameraSettingsManager.SetSettings(this);
        }

        /// 
        /// Checks if the ZED camera is connected.
        /// 检查是否连接了ZED相机。
        /// 
        /// The C++ SDK version of this call returns the number of connected ZEDs. But multiple ZEDs aren't supported in the Unity plugin.
        /// 此调用的C ++ SDK版本返回已连接ZED的数量。但是Unity插件不支持多个ZED。
        /// True if ZED is connected.
        public static bool IsZedConnected()
        {
            return Convert.ToBoolean(dllz_is_zed_connected());
        }

        /// 
        /// Gets the version of the currently installed ZED SDK.
        /// 获取当前安装的ZED SDK的版本。
        /// 
        /// ZED SDK version as a string in the format MAJOR.MINOR.PATCH.
        public static string GetSDKVersion()
        {
            return PtrToStringUtf8(dllz_get_sdk_version());
        }

        /// 
        /// Checks if the camera has been initialized and the plugin has been loaded. Throws exceptions otherwise.
        /// 检查相机是否已初始化以及插件是否已加载。否则抛出异常。
        /// 
        private void AssertCameraIsReady()
        {
            if (!cameraReady)
                throw new Exception("ZED camera is not connected or Init() was not called.");

            if (!pluginIsReady)
                throw new Exception("Could not resolve ZED plugin dependencies.");
        }

        /// 
        /// Deploys an event that causes the textures to be updated with images received from the ZED.
        /// Should be called after RetrieveTextures() so there are new images available.
        /// 部署一个事件,该事件使纹理使用从ZED接收的图像进行更新。
        /// 应该在RetrieveTextures()之后调用,以便有新的图像可用。
        /// Lance:大概的意思是,底层SDK采集了新的图片,然后才能更新纹理
        /// 
        public void UpdateTextures()
        {
            GL.IssuePluginEvent(GetRenderEventFunc(), 1); //这个函数还是不大懂
        }


        / SINGLE PIXEL UTILITY FUNCTIONS 
        /// 单一像素操作,这部分对我们来说比较有用
        /// 
        /// Gets the current depth value of a pixel in the UNITS specified when the camera was started with Init().
        /// May result in errors if the ZED image does not fill the whole screen.
        /// 使用Init()启动相机时,获取指定的UNITS中像素的当前深度值。
        /// 如果ZED图像不能填满整个屏幕,则可能会导致错误。
        /// Lance:这边指的是获取电脑屏幕上某个点的深度数据,如果我们获取的图片与电脑屏幕没有对齐的话,可能会发生错误
        /// The pixel's screen space coordinates as a Vector3.
        /// The Z component is unused - designed to take input from Input.mousePosition.
        /// 这里的参数是三维的向量,但是实际上在Z维度上是不起作用的,实际上就是图像坐标
        /// Depth value as a float.  浮点类型的深度值
        /// 
        public float GetDepthValue(Vector3 pixel)
        {
            if (!cameraReady)
            {
                return -1;
            }
            //屏幕宽度指的是显示频的屏幕宽度
            float posX = (float) ImageWidth * (float) ((float) pixel.x / (float) Screen.width); //这部分的操作是啥,
            float posY = ImageHeight * (1 - (float) pixel.y / (float) Screen.height); //这部分的操作是啥,

            posX = Mathf.Clamp(posX, 0, ImageWidth); //限制数值的范围,保证稳定性
            posY = Mathf.Clamp(posY, 0, ImageHeight);
            float d = dllz_get_depth_value(CameraID, (uint) posX, (uint) posY); //这个底层接口其实我们也可以调用,调来获得某个像素的深度值
            return d;
        }

        /// 
        /// Gets the current Euclidean distance (sqrt(x²+y²+z²)) of the targeted pixel of the screen to the camera.
        /// May result in errors if the ZED image does not fill the whole screen.
        /// 获取屏幕目标像素到相机的当前欧几里得距离(sqrt(x²+y²+z²))。
        /// 如果ZED图像不能填满整个屏幕,则可能会导致错误。
        /// The pixel's screen space coordinates as a Vector3.
        /// The Z component is unused - designed to take input from Input.mousePosition.
        /// 像素的屏幕空间坐标为Vector3。 /// Z组件未使用-旨在从Input.mousePosition获取输入。
        /// Distance as a float.
        /// Lance:这边的输入是电脑屏幕上的像素坐标,不是图像上的像素坐标
        /// 
        public float GetDistanceValue(Vector3 pixel)
        {
            if (!cameraReady) //Do nothing if the ZED isn't initialized.
            {
                return -1;
            }

            float posX = ImageWidth * (float) pixel.x / (float) Screen.width;
            float posY = ImageHeight * (1 - (float) pixel.y / (float) Screen.height);
            posX = Mathf.Clamp(posX, 0, ImageWidth); //把posX限定在这个范围里面,以防万一出现问题
            posY = Mathf.Clamp(posY, 0, ImageHeight);

            return dllz_get_distance_value(CameraID, (uint) posX, (uint) posY);
        }

        /// 
        /// Gets the position of a camera-space pixel relative to the camera frame.
        /// 获得相机空间下的位置, 和 camera frame相关 。
        /// The pixel's screen space coordinates as a Vector3. //电脑屏幕的图象坐标
        /// The Z component is unused - designed to take input from Input.mousePosition.
        /// Position relative to the camera.相机空间下的坐标
        /// True if successful.
        /// Lance:这个是我们需要的,就是获得某个点云点,但是有一个问题就是,这边的输入是屏幕坐标
        /// 
        public bool GetXYZValue(Vector3 pixel, out Vector4 xyz)
        {
            if (!cameraReady) //Do nothing if the ZED isn't initialized.
            {
                xyz = Vector3.zero;
                return false;
            }

            float posX = (float) ImageWidth * (float) ((float) pixel.x / (float) Screen.width);
            float posY = ImageHeight * (1 - (float) pixel.y / (float) Screen.height);
            posX = Mathf.Clamp(posX, 0, ImageWidth);
            posY = Mathf.Clamp(posY, 0, ImageHeight);
            bool r = dllz_get_xyz_value(CameraID, (uint) posX, (uint) posY, out xyz) != 0; //这个函数接口是我们要用的,可以重新定义一下。
            return r;
        }


        /// 
        /// Gets the normal of a camera-space pixel. The normal is relative to the camera.
        /// Use cam.worldToCameraMatrix.inverse to transform it to world space.
        /// Note that ZEDSupportFunctions contains high-level versions of this function that are easier to use.
        /// 获取相机空间下的某个法线。法线相对于相机。
        /// 使用cam.worldToCameraMatrix.inverse将其转换为世界空间。
        /// 请注意,ZEDSupportFunctions包含此函数的高级版本,这些版本更易于使用。
        /// The pixel's screen space coordinates as a Vector3.
        /// The Z component is unused - designed to take input from Input.mousePosition.
        /// Normal value of the pixel as a Vector4.注意这边是一个四维向量
        /// True if successful.
        /// 
        public bool GetNormalValue(Vector3 pixel, out Vector4 normal)
        {
            if (!cameraReady) //Do nothing if the ZED isn't initialized.
            {
                normal = Vector3.zero;
                return false;
            }

            float posX = (float) ImageWidth * (float) ((float) pixel.x / (float) Screen.width);
            float posY = ImageHeight * (1 - (float) pixel.y / (float) Screen.height);

            posX = Mathf.Clamp(posX, 0, ImageWidth);
            posY = Mathf.Clamp(posY, 0, ImageHeight);

            bool r = dllz_get_normal_value(CameraID, (uint) posX, (uint) posY, out normal) != 0; //某个法向向量
            return r;
        }

        /// 
        /// Initializes and begins the spatial mapping processes.
        /// 初始化并开始空间映射过程
        /// 
        /// Spatial mapping resolution in meters.空间映射分辨率,以米为单位。
        /// Maximum scanning range in meters.最大扫描范围,以米为单位。
        /// True to scan surface textures in addition to geometry.除几何图形外,还适用于扫描表面纹理。
        /// 
        public sl.ERROR_CODE EnableSpatialMapping(float resolution_meter, float max_range_meter,
            bool saveTexture = false)
        {
            sl.ERROR_CODE spatialMappingStatus = ERROR_CODE.FAILURE;
            lock (grabLock)
            {
                spatialMappingStatus = (sl.ERROR_CODE) dllz_enable_spatial_mapping(CameraID, resolution_meter,
                    max_range_meter, System.Convert.ToInt32(saveTexture));
            }

            return spatialMappingStatus;
        }

        /// 
        /// Disables the Spatial Mapping process.
        /// 禁用空间映射过程。
        /// 
        public void DisableSpatialMapping()
        {
            lock (grabLock)
            {
                dllz_disable_spatial_mapping(CameraID);
            }
        }

        /// 
        /// Updates the internal version of the mesh and returns the sizes of the meshes.
        /// 更新网格的内部版本并返回网格的大小。
        /// Lance:这个功能不是很明确
        /// 
        /// Array of the number of vertices in each submesh.每个子网格中顶点数量的数组
        /// Array of the number of triangles in each submesh.每个子网格中三角形数量的数组。
        /// Number of submeshes.子网格数
        /// List of all submeshes updated since the last update.自上次更新以来已更新的所有子网格的列表
        /// Total number of updated vertices in all submeshes.所有子网格中更新的顶点总数
        /// Total number of updated triangles in all submeshes.所有子网格中更新的顶点总数
        /// Maximum number of submeshes that can be handled.可以处理的最大子网格数
        /// Error code indicating if the update was successful, and why it wasn't otherwise.错误代码,指示更新是否成功,以及为什么更新失败。
        public sl.ERROR_CODE UpdateMesh(int[] nbVerticesInSubmeshes, int[] nbTrianglesInSubmeshes, ref int nbSubmeshes,
            int[] updatedIndices, ref int nbVertices, ref int nbTriangles, int nbSubmeshMax)
        {
            sl.ERROR_CODE err = sl.ERROR_CODE.FAILURE;
            err = (sl.ERROR_CODE) dllz_update_mesh(CameraID, nbVerticesInSubmeshes, nbTrianglesInSubmeshes,
                ref nbSubmeshes, updatedIndices, ref nbVertices, ref nbTriangles, nbSubmeshMax);
            return err;
        }

        /// 
        /// Retrieves all chunks of the generated mesh. Call UpdateMesh() before calling this.
        /// Vertex and triangle arrays must be at least of the sizes returned by UpdateMesh (nbVertices and nbTriangles).
        /// 检索生成的网格的所有块。在调用此方法之前,请先调用UpdateMesh()。
        /// 顶点和三角形数组必须至少具有UpdateMesh返回的大小(nbVertices和nbTriangles)。
        /// 
        /// Vertices of the mesh.
        /// Triangles, formatted as the index of each triangle's three vertices in the vertices array.
        /// Maximum number of submeshes that can be handled.
        /// Error code indicating if the retrieval was successful, and why it wasn't otherwise.
        public sl.ERROR_CODE RetrieveMesh(Vector3[] vertices, int[] triangles, int nbSubmeshMax, Vector2[] uvs,
            IntPtr textures)
        {
            return (sl.ERROR_CODE) dllz_retrieve_mesh(CameraID, vertices, triangles, nbSubmeshMax, uvs, textures);
        }

        /// 
        /// Starts the mesh generation process in a thread that doesn't block the spatial mapping process.
        /// ZEDSpatialMappingHelper calls this each time it has finished applying the last mesh update.
        /// 在不阻塞空间映射过程的线程中启动网格生成过程。
        /// ZEDSpatialMappingHelper每次完成应用最后一个网格更新时都会调用此方法。
        /// 
        public void RequestMesh()
        {
            dllz_request_mesh_async(CameraID);
        }

        /// 
        /// Sets the pause state of the data integration mechanism for the ZED's spatial mapping.
        /// 为ZED的空间映射设置数据集成机制的暂停状态。
        /// 
        /// If true, the integration is paused. If false, the spatial mapping is resumed.
        public void PauseSpatialMapping(bool status)
        {
            dllz_pause_spatial_mapping(CameraID, status);
        }

        /// 
        /// Returns the mesh generation status. Useful for knowing when to update and retrieve the mesh.
        /// 返回网格生成状态。有助于了解何时更新和检索网格。
        /// 
        public sl.ERROR_CODE GetMeshRequestStatus()
        {
            return (sl.ERROR_CODE) dllz_get_mesh_request_status_async(CameraID);
        }

        /// 
        /// Saves the scanned mesh in a specific file format.
        /// 将扫描的网格保存为特定的文件格式。
        /// 
        /// Path and filename of the mesh.
        /// File format (extension). Can be .obj, .ply or .bin.
        public bool SaveMesh(string filename, MESH_FILE_FORMAT format)
        {
            return dllz_save_mesh(CameraID, filename, format);
        }

        /// 
        /// Loads a saved mesh file. ZEDSpatialMapping then configures itself as if the loaded mesh was just scanned.
        /// 加载保存的网格文件。然后,ZEDSpatialMapping将自身配置为就像刚刚扫描加载的网格一样。
        /// 
        /// Path and filename of the mesh. Should include the extension (.obj, .ply or .bin).
        /// Array of the number of vertices in each submesh.
        /// Array of the number of triangles in each submesh.
        /// Number of submeshes.
        /// List of all submeshes updated since the last update.
        /// Total number of updated vertices in all submeshes.
        /// Total number of updated triangles in all submeshes.
        /// Maximum number of submeshes that can be handled.
        /// Array containing the sizes of all the textures (width, height) if applicable.
        public bool LoadMesh(string filename, int[] nbVerticesInSubmeshes, int[] nbTrianglesInSubmeshes,
            ref int nbSubmeshes, int[] updatedIndices,
            ref int nbVertices, ref int nbTriangles, int nbSubmeshMax, int[] textureSize = null)
        {
            return dllz_load_mesh(CameraID, filename, nbVerticesInSubmeshes, nbTrianglesInSubmeshes, ref nbSubmeshes,
                updatedIndices, ref nbVertices,
                ref nbTriangles, nbSubmeshMax, textureSize);
        }

        /// 
        /// Filters a mesh to remove triangles while still preserving its overall shape (though less accurate).
        /// 过滤网格以删除三角形,同时仍保留其总体形状(尽管精度较低)。
        /// Lance:大概的意思就是一些网格可能是在同一个平面上的,那么就可以结合在一起,减少网格的定点数,
        /// 
        /// Filter level. Higher settings remove more triangles.
        /// Array of the number of vertices in each submesh.
        /// Array of the number of triangles in each submesh.
        /// Number of submeshes.
        /// List of all submeshes updated since the last update.
        /// Total number of updated vertices in all submeshes.
        /// Total number of updated triangles in all submeshes.
        /// Maximum number of submeshes that can be handled.
        public bool FilterMesh(FILTER filterParameters, int[] nbVerticesInSubemeshes, int[] nbTrianglesInSubemeshes,
            ref int nbSubmeshes, int[] updatedIndices, ref int nbVertices, ref int nbTriangles, int nbSubmeshMax)
        {
            return dllz_filter_mesh(CameraID, filterParameters, nbVerticesInSubemeshes, nbTrianglesInSubemeshes,
                ref nbSubmeshes, updatedIndices, ref nbVertices, ref nbTriangles, nbSubmeshMax);
        }

        /// 
        /// Applies the scanned texture onto the internal scanned mesh.
        /// You will need to call RetrieveMesh() with uvs and textures to get the result into Unity.
        /// 将扫描的纹理应用于内部扫描的网格。
        /// 您将需要使用uvs和纹理调用RetrieveMesh()才能将结果导入Unity。
        /// Lance:这部分内容还需要理解一下
        /// 
        /// Array of the number of vertices in each submesh.
        /// Array of the number of triangles in each submesh.
        /// Number of submeshes.
        /// List of all submeshes updated since the last update.
        /// Total number of updated vertices in all submeshes.
        /// Total number of updated triangles in all submeshes.
        ///  Vector containing the size of all the texture (width, height). 
        /// Maximum number of submeshes that can be handled.
        /// 
        public bool ApplyTexture(int[] nbVerticesInSubmeshes, int[] nbTrianglesInSubmeshes, ref int nbSubmeshes,
            int[] updatedIndices, ref int nbVertices, ref int nbTriangles, int[] textureSize, int nbSubmeshMax)
        {
            return dllz_apply_texture(CameraID, nbVerticesInSubmeshes, nbTrianglesInSubmeshes, ref nbSubmeshes,
                updatedIndices, ref nbVertices, ref nbTriangles, textureSize, nbSubmeshMax);
        }

        /// 
        /// Gets the current state of spatial mapping.
        /// 获取空间映射的当前状态。
        /// 
        /// 
        public SPATIAL_MAPPING_STATE GetSpatialMappingState()
        {
            return (sl.SPATIAL_MAPPING_STATE) dllz_get_spatial_mapping_state(CameraID);
        }

        /// 
        /// Gets a vector pointing toward the direction of gravity. This is estimated from a 3D scan of the environment,
        /// and as such, a scan must be started/finished for this value to be calculated.
        /// If using the ZED Mini, this isn't required thanks to its IMU.
        /// 获取指向重力方向的向量。这是根据对环境的3D扫描估算的,
        /// 因此必须开始/完成扫描才能计算该值。
        /// 如果使用ZED Mini,则由于其IMU而不需要。
        /// Lance:  Mini版本有Imu自动可以检测到重力方向
        /// 
        /// Vector3 pointing downward.
        public Vector3 GetGravityEstimate()
        {
            Vector3 v = Vector3.zero;
            dllz_spatial_mapping_get_gravity_estimation(CameraID, ref v);
            return v;
        }

        /// 
        /// Consolidates the chunks from a scan. This is used to turn lots of small meshes (which are efficient for
        /// the scanning process) into several large meshes (which are more convenient to work with).
        /// 合并扫描中的块。这用于将许多小网格(对扫描过程有效)
        /// 变成几个大网格(使用起来更方便)。
        /// 
        /// 
        /// Array of the number of vertices in each submesh.
        /// Array of the number of triangles in each submesh.
        /// Number of submeshes.
        /// List of all submeshes updated since the last update.
        /// Total number of updated vertices in all submeshes.
        /// Total number of updated triangles in all submeshes.
        public void MergeChunks(int numberFaces, int[] nbVerticesInSubmeshes, int[] nbTrianglesInSubmeshes,
            ref int nbSubmeshes, int[] updatedIndices, ref int nbVertices, ref int nbTriangles, int nbSubmesh)
        {
            dllz_spatial_mapping_merge_chunks(CameraID, numberFaces, nbVerticesInSubmeshes, nbTrianglesInSubmeshes,
                ref nbSubmeshes, updatedIndices, ref nbVertices, ref nbTriangles, nbSubmesh);
        }

        /// 
        /// Retrieves a measure texture from the ZED SDK and loads it into a ZEDMat. Use this to get an individual
        /// texture from the last grabbed frame with measurements in every pixel - such as a depth map, confidence map, etc.
        /// Measure textures are not human-viewable but don't lose accuracy, unlike image textures.
        /// 从ZED SDK检索度量纹理并将其加载到ZEDMat中。
        /// 使用此参数从最后一个抓取的帧中获取单个
        /// 纹理,每个像素中都有测量值-例如深度图,置信度图等。
        /// 测量纹理不是人类可见的,但不会失去准确性,这与图像纹理不同。
        /// Lance:这个函数就是用来获取点云和实际深度数据的
        /// 
        /// If you want to access the texture via script, you'll usually want to specify CPU memory. Then you can use
        /// Marshal.Copy to move them into a new byte array, which you can load into a Texture2D.
        /// 如果要通过脚本访问纹理,通常需要指定CPU内存。然后可以使用Marshal.Copy将其移动到新的字节数组中,然后可以将其加载到Texture2D中。
        /// RetrieveMeasure() calls Camera::retrieveMeasure() in the C++ SDK. For more info, read:
        /// https://www.stereolabs.com/developers/documentation/API/v2.5.1/classsl_1_1Camera.html#af799d12342a7b884242def5588a7f
        /// 
        /// ZEDMat to fill with the new texture.
        /// Measure type (depth, confidence, xyz, etc.)
        /// Whether the image should be on CPU or GPU memory.
        /// Resolution of the texture.
        /// Error code indicating if the retrieval was successful, and why it wasn't otherwise.
        public sl.ERROR_CODE RetrieveMeasure(sl.ZEDMat mat, sl.MEASURE measure,
            sl.ZEDMat.MEM mem = sl.ZEDMat.MEM.MEM_CPU, sl.Resolution resolution = new sl.Resolution())
        {
            return (sl.ERROR_CODE) (dllz_retrieve_measure(CameraID, mat.MatPtr, (int) measure, (int) mem, resolution));
        }

        /// 
        /// Retrieves an image texture from the ZED SDK and loads it into a ZEDMat. Use this to get an individual
        /// texture from the last grabbed frame in a human-viewable format. Image textures work for when you want the result to be visible,
        /// such as the direct RGB image from the camera, or a greyscale image of the depth. However it will lose accuracy if used
        /// to show measurements like depth or confidence, unlike measure textures.
        /// 从ZED SDK检索图像纹理并将其加载到ZEDMat中。使用此功能以人类可见的格式从上一个抓取的帧中获取单独的
        /// 纹理。图像纹理适用于希望结果可见的
        /// 例如来自相机的直接RGB图像或深度的灰度图像。但是,如果使用
        /// 来显示深度或置信度之类的度量,则它会失去准确性,这与度量纹理不同。
        /// Lance:只能用于彩色图象和深度图象, 不能用于置信度矩阵或者精确的深度数据
        /// 
        /// If you want to access the texture via script, you'll usually want to specify CPU memory. Then you can use
        /// Marshal.Copy to move them into a new byte array, which you can load into a Texture2D. Note that you may need to
        /// change the color space and/or flip the image.
        /// 如果要通过脚本访问纹理,通常需要指定CPU内存。然后可以使用
        /// Marshal.Copy将其移动到新的字节数组中,然后可以将其加载到Texture2D中。请注意,您可能需要
        /// 更改颜色空间和/或翻转图像。
        /// Lance:如果想要获得图象数据的话,需要调用这边的函数
        /// RetrieveMeasure() calls Camera::retrieveMeasure() in the C++ SDK. For more info, read:
        /// https://www.stereolabs.com/developers/documentation/API/v2.5.1/classsl_1_1Camera.html#ac40f337ccc76cacd3412b93f7f4638e2
        /// 
        /// ZEDMat to fill with the new texture.
        /// Image type (left RGB, right depth map, etc.)
        /// Whether the image should be on CPU or GPU memory.
        /// Resolution of the texture.
        /// Error code indicating if the retrieval was successful, and why it wasn't otherwise.
        public sl.ERROR_CODE RetrieveImage(sl.ZEDMat mat, sl.VIEW view, sl.ZEDMat.MEM mem = sl.ZEDMat.MEM.MEM_CPU,
            sl.Resolution resolution = new sl.Resolution())
        {
            return (sl.ERROR_CODE) (dllz_retrieve_image(CameraID, mat.MatPtr, (int) view, (int) mem, resolution));
        }

        /// 
        /// Computes offsets of the optical centers used to line up the ZED's images properly with Unity cameras.
        /// Called in ZEDRenderingPlane after the ZED finished initializing.
        /// 计算用于与Unity相机正确对齐ZED图像的光学中心的偏移量。
        /// 在ZED完成初始化之后,调用ZEDRenderingPlane。
        /// 
        /// Distance from a camera in the ZED rig to the quad/Canvas object holding the ZED image.
        /// ZED的摄影机到包含ZED图像的Quad / Canvas对象的距离。
        /// 
        public Vector4 ComputeOpticalCenterOffsets(float planeDistance)
        {
            IntPtr p = IntPtr.Zero;
            sl.CalibrationParameters calib = GetCalibrationParameters(false);
            sl.Resolution imageResolution = new sl.Resolution((uint) this.ImageWidth, (uint) this.ImageHeight);

            Vector4 calibLeft = new Vector4(calib.leftCam.fx, calib.leftCam.fy, calib.leftCam.cx, calib.leftCam.cy);
            Vector4 calibRight =
                new Vector4(calib.rightCam.fx, calib.rightCam.fy, calib.rightCam.cx, calib.rightCam.cy);

            p = dllz_compute_optical_center_offsets(ref calibLeft, ref calibRight, imageResolution, planeDistance);
            if (p == IntPtr.Zero)
            {
                return new Vector4();
            }

            Vector4 parameters = (Vector4) Marshal.PtrToStructure(p, typeof(Vector4));
            return parameters;
        }

        
        /// Plane Detection  ///
        


        /// 
        /// Looks for a plane in the visible area that is likely to represent the floor.
        /// Use ZEDPlaneDetectionManager.DetectFloorPlane for a higher-level version that turns planes into GameObjects.
        /// 在可能代表地板的可见区域中寻找一个平面。
        /// 将ZEDPlaneDetectionManager.DetectFloorPlane用于将平面转换成GameObjects的更高版本。
        /// 
        /// Data on the detected plane.
        /// Height of the camera from the newly-detected floor.
        /// Prior rotation.
        /// Prior position.
        /// 
        public sl.ERROR_CODE findFloorPlane(ref ZEDPlaneGameObject.PlaneData plane, out float playerHeight,
            Quaternion priorQuat, Vector3 priorTrans)
        {
            IntPtr p = IntPtr.Zero;
            Quaternion out_quat = Quaternion.identity;
            Vector3 out_trans = Vector3.zero;
            p = dllz_find_floor_plane(CameraID, out out_quat, out out_trans, priorTrans, priorTrans);
            plane.Bounds = new Vector3[256];
            playerHeight = 0;

            if (p != IntPtr.Zero)
            {
                plane = (ZEDPlaneGameObject.PlaneData) Marshal.PtrToStructure(p, typeof(ZEDPlaneGameObject.PlaneData));
                playerHeight = out_trans.y;
                return (sl.ERROR_CODE) plane.ErrorCode;
            }
            else
                return sl.ERROR_CODE.FAILURE;
        }

        /// 
        /// Using data from a detected floor plane, updates supplied vertex and triangle arrays with
        /// data needed to make a mesh that represents it. These arrays are updated directly from the wrapper.
        /// 使用来自检测到的地板平面的数据,使用更新提供的顶点和三角形阵列,以制作表示它的网格。这些数组直接从包装器更新。
        /// 
        /// Array to be filled with mesh vertices.
        /// Array to be filled with mesh triangles, stored as indexes of each triangle's points.
        /// Total vertices in the mesh.
        /// Total triangle indexes (3x number of triangles).
        /// 
        public int convertFloorPlaneToMesh(Vector3[] vertices, int[] triangles, out int numVertices,
            out int numTriangles)
        {
            return dllz_convert_floorplane_to_mesh(CameraID, vertices, triangles, out numVertices, out numTriangles);
        }

        /// 
        /// Checks for a plane in the real world at given screen-space coordinates.
        /// Use ZEDPlaneDetectionManager.DetectPlaneAtHit() for a higher-level version that turns planes into GameObjects.
        /// 在给定的屏幕空间坐标处检查现实世界中的平面。
        /// 将ZEDPlaneDetectionManager.DetectPlaneAtHit()用于将平面转换成GameObjects的更高版本。
        /// 
        /// Data on the detected plane.检测平面上的数据。
        /// Point on the ZED image to check for a plane.在ZED图像上指向以检查平面。
        /// 
        public sl.ERROR_CODE findPlaneAtHit(ref ZEDPlaneGameObject.PlaneData plane, Vector2 screenPos)
        {
            IntPtr p = IntPtr.Zero;
            Quaternion out_quat = Quaternion.identity;
            Vector3 out_trans = Vector3.zero;

            float posX = (float) ImageWidth * (float) ((float) screenPos.x / (float) Screen.width);
            float posY = ImageHeight * (1 - (float) screenPos.y / (float) Screen.height);
            posX = Mathf.Clamp(posX, 0, ImageWidth);
            posY = Mathf.Clamp(posY, 0, ImageHeight);

            p = dllz_find_plane_at_hit(CameraID, new Vector2(posX, posY), true);
            plane.Bounds = new Vector3[256];

            if (p != IntPtr.Zero)
            {
                plane = (ZEDPlaneGameObject.PlaneData) Marshal.PtrToStructure(p, typeof(ZEDPlaneGameObject.PlaneData));
                return (sl.ERROR_CODE) plane.ErrorCode;
            }
            else
                return sl.ERROR_CODE.FAILURE;
        }

        /// 
        /// Using data from a detected hit plane, updates supplied vertex and triangle arrays with
        /// data needed to make a mesh that represents it. These arrays are updated directly from the wrapper.
        /// 使用来自检测到的击中平面的数据,用来更新提供的顶点和三角形阵列,以制作表示它的网格。这些数组直接从包装器更新。
        /// Lance:这部分的知识点还需要补一下
        /// Lance: 仅在ZEDPlaneDetectionManager中被调用一次
        /// 
        /// Array to be filled with mesh vertices.要用网格顶点填充的数组。
        /// Array to be filled with mesh triangles, stored as indexes of each triangle's points.用网格三角形填充的数组,存储为每个三角形点的索引。
        /// Total vertices in the mesh.网格中的总顶点。
        /// Total triangle indexes (3x number of triangles).三角形索引总数(三角形的3倍)。
        /// 
        public int convertHitPlaneToMesh(Vector3[] vertices, int[] triangles, out int numVertices, out int numTriangles)
        {
            return dllz_convert_hitplane_to_mesh(CameraID, vertices, triangles, out numVertices, out numTriangles);
        }


        
        /// Streaming Module ///
        

        /// 
        /// Creates an streaming pipeline.
        /// 创建一个流管道
        /// 
        /// 
        /// Streaming parameters: See sl::StreamingParameters of ZED SDK. See ZED SDK API doc for more informations
        /// 
        /// An ERROR_CODE that defines if the streaming pipe was successfully created
        /// 一个ERROR_CODE,定义是否成功创建了流管道
        public ERROR_CODE EnableStreaming(STREAMING_CODEC codec = STREAMING_CODEC.AVCHD_BASED, uint bitrate = 8000,
            ushort port = 30000, int gopSize = -1, bool adaptativeBitrate = false, int chunk_size = 32768)
        {
            int doAdaptBitrate = adaptativeBitrate ? 1 : 0;
            return (ERROR_CODE) dllz_enable_streaming(CameraID, codec, bitrate, port, gopSize, doAdaptBitrate,
                chunk_size);
        }

        /// 
        /// Tells if streaming is running or not.
        /// 告知流媒体是否正在运行。
        /// 
        ///  false if streaming is not enabled, true if streaming is on
        public bool IsStreamingEnabled()
        {
            int res = dllz_is_streaming_enabled(CameraID);
            if (res == 1)
                return true;
            else
                return false;
        }

        /// 
        /// Stops the streaming pipeline.
        /// 停止流传输管道。
        /// 
        public void DisableStreaming()
        {
            dllz_disable_streaming(CameraID);
        }


        
        /// Save utils fct   ///
        

        /// 
        /// Save current image (specified by view) in a file defined by filename
        /// Supported formats are jpeg and png. Filename must end with either .jpg or .png
        /// 将当前图像(由视图指定)保存在文件名定义的文件中
        /// 支持的格式为jpeg和png。文件名必须以.jpg或.png结尾
        /// 
        public sl.ERROR_CODE SaveCurrentImageInFile(sl.VIEW view, String filename)
        {
            sl.ERROR_CODE err = (sl.ERROR_CODE) dllz_save_current_image(CameraID, view, filename);
            return err;
        }

        /// 
        /// Save the current depth in a file defined by filename.
        /// Supported formats are PNG,PFM and PGM
        /// 将当前深度保存在filename定义的文件中。
        /// 支持的格式为PNG,PFM和PGM
        /// 
        ///  defines left (0) or right (1) depth
        ///  filename must end with .png, .pfm or .pgm
        /// 
        public sl.ERROR_CODE SaveCurrentDepthInFile(int side, String filename)
        {
            sl.ERROR_CODE err = (sl.ERROR_CODE) dllz_save_current_depth(CameraID, side, filename);
            return err;
        }

        /// 
        /// Save the current point cloud in a file defined by filename.
        /// Supported formats are PLY,VTK,XYZ and PCD
        /// 将当前点云保存在filename定义的文件中。
        /// 支持的格式为PLY,VTK,XYZ和PCD
        /// Lance:这是在Unity插件里面第一次看到点云的概念啊
        /// 
        /// defines left (0) or right (1) point cloud,哪一边相机的点云
        ///  filename must end with .ply, .xyz , .vtk or .pcd 
        /// 
        public sl.ERROR_CODE SaveCurrentPointCloudInFile(int side, String filename)
        {
            sl.ERROR_CODE err = (sl.ERROR_CODE) dllz_save_current_point_cloud(CameraID, side, filename);
            return err;
        }

        
        /// Object detection ///
        

        /// 
        /// Enable object detection module
        /// 启用对象检测模块
        /// 
        public sl.ERROR_CODE EnableObjectsDetection(ref dll_ObjectDetectionParameters od_params)
        {
            sl.ERROR_CODE objDetectStatus = ERROR_CODE.FAILURE;
            lock (grabLock)
            {
                objDetectStatus = (sl.ERROR_CODE) dllz_enable_objects_detection(CameraID, ref od_params);
            }

            return objDetectStatus;
        }

        /// 
        /// Disable object detection module and release the resources.
        /// 禁用对象检测模块并释放资源
        /// 
        public void DisableObjectsDetection()
        {
            lock (grabLock)
            {
                dllz_disable_objects_detection(CameraID);
            }
        }

        /// 
        /// Pause or Unpause the object detection
        /// 暂停或取消暂停对象检测
        /// 
        /// 
        public void PauseObjectsDetection(bool status)
        {
            lock (grabLock)
            {
                dllz_pause_objects_detection(CameraID, status);
            }
        }

        /// 
        /// Retrieve object detection data
        /// 检索物体检测数据
        /// 
        ///  Object detection runtime parameters,
        /// 对象检测运行时参数
        ///  ObjectsFrameSDK that contains all the detection data,
        /// 包含所有检测数据的ObjectsFrameSDK
        /// 
        public sl.ERROR_CODE RetrieveObjectsDetectionData(ref dll_ObjectDetectionRuntimeParameters od_params,
            ref ObjectsFrameSDK objFrame)
        {
            return (sl.ERROR_CODE) dllz_retrieve_objects_data(CameraID, ref od_params, ref objFrame);
        }
    } //Zed Camera class
} // namespace sl
    
 

你可能感兴趣的:(Unity+C#,ZED相机)