设计模式 反射 ipv4 golang 哨兵模式 sorting graph oauth reference jaxb grid angular ui router Backbonejs nginx学习视频 pmp视频教程下载 electron教程 python转16进制 查看rabbitmq版本 mysql新增用户和权限 maven插件 linux全局搜索文件 flutter 缺点 docker保存镜像 pythoninput python学习文档 java程序实例 java数组删除 java中文文档 linux安装 垃圾邮件数据集 customerrors unix操作系统下载 黑白照片一键变彩色 iphone滚动截屏 kmservice ps选择反向快捷键 如何给黑白照片上色 系统维护工具 微信骰子表情包 深渊碎片
当前位置: 首页 > 学习教程  > 编程语言

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

2020/8/31 15:33:01 文章标签:

文章目录

  • Zed-Unity插件代码注释——ZEDCamera.CS
    • 引言
    • 基础环境
    • ZedCamera.cs脚本介绍
    • ZedCamera.cs代码(注释后)

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脚本介绍

  • 脚本位置:
    在这里插入图片描述

  • 脚本的功能:
    这个脚本是插件里面较为底层的脚本,定义了一个命名空间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 //定义命名空间
{
    /// <summary>
    /// 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和
    /// 低级逻辑的外部调用,以处理发送给它的数据或从中接收的数据
    /// </summary>
    /// <remarks>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.</remarks>
    /// ZEDManager组件在Awake()中创建一个ZEDCamera实例并处理所有初始化。
    /// 大多数ZED功能可以通过ZEDManager或其他高级管理器组件简单地在Unity中处理
    /// ((ZEDSpatialMappingManager,ZEDPlaneDetectionManager等)
    /// ZEDCamera通过CreateTextureImageType()和CreateTextureMeasureType()创建的纹理
    /// 只要有新帧,包装器就会自动更新。它们代表一种特定的输出,例如左RGB图像或相对于右传感器的深度。这样,您只需要一个texture就可以
    /// 因为它可以被所有需要它的脚本简单地重用。因此,在ZEDCamera中创建的纹理
    /// 由其类型(图像或度量)索引,然后由每种类型的选项索引。如果脚本需要某种输出
    /// 则ZEDCamera创建一个新的,或者引用现有的输出。
    public class ZEDCamera
    {
        /// <summary>
        /// Type of textures requested.
        /// 定义几个纹理的类型
        /// </summary>
        public enum TYPE_VIEW //定义一个枚举类型,
        {
            /// 枚举类型的相关知识 https://www.cnblogs.com/liujianshe1990-/p/10247930.html
            /// <summary>
            /// Image-type texture. Human-viewable but loses measurement accuracy.
            /// 图像类型的纹理。肉眼可见但会失去测量精度。
            /// Lance:指的应该就是采用RGB图像显示把
            /// </summary>
            RETRIEVE_IMAGE,

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

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

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

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

        /// <summary>
        /// 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:不是很明白这边的东西
        /// </summary>
        private Dictionary<int, Dictionary<int, Texture2D>> textures; // 注册一个纹理的列表,是两个嵌套字典,最里面的元素内容是2D的纹理

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

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

        /// <summary>
        /// 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的宽度
        /// </summary>
        public int ImageWidth
        {
            get { return imageWidth; }
        }

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

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

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

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


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

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

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

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

        /// <summary>
        /// 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输出限制,而不是系统性能限制。
        /// </summary>
        private uint fpsMax = 60; //Defaults to HD720 resolution's output.

        /// <summary>
        /// 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输出限制,而不是系统性能限制。
        /// </summary>
        public float GetRequestedCameraFPS() //获得最大采集帧率
        {
            return fpsMax;
        }

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

        /// <summary>
        /// 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。
        /// </summary><remarks>Note: the plugin will allow using the original ZED
        /// for pass-through but it will feel quite uncomfortable due to the baseline.</remarks>
        /// 该插件将允许使用原始的ZED作为AR的设备,但是由于基线不同,它会让用户感到非常不舒服
        /// Lance:最好是用ZED设备的mini版本
        public bool IsHmdCompatible //判断AR头盔是否兼容
        {
            get { return cameraModel == sl.MODEL.ZED_M; }
        }

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

        // /// <summary>
        // /// Layer that the ZED can't see, but overlay cameras created by ZEDMeshRenderer and ZEDPlaneRenderer can.
        // ///
        // /// </summary>
        // int tagInvisibleToZED = 16;
        /// <summary>
        /// Layer that the ZED can't see, but overlay cameras created by ZEDMeshRenderer and ZEDPlaneRenderer can.
        /// ZED无法看到的图层,但是可以覆盖由ZEDMeshRenderer和ZEDPlaneRenderer创建的摄影机。
        /// Lance:这边设置的是一个图层标签,标签对应的图层不会在AR模式下被看到,这边还不是特别理解,先往下看吧
        /// </summary>
        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  就注释一部分,这部分的内容我们一般不会做修改。

        /// <summary>
        /// Current Plugin Version.
        /// 当前插件版本
        /// </summary>
        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

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

        /// <summary>
        /// 释放指定id的实例
        /// </summary>
        /// <param name="id"></param>
        public static void UnloadInstance(int id) //释放指定的实例
        {
            dllz_unload_instance(id);
        }

        /// <summary>
        /// 计算偏移,用于校正ZED相机在Unity中的位姿
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="nbVectors"></param>
        /// <param name="rotation"></param>
        /// <param name="translation"></param>
        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;
        }

        /// <summary>
        /// Return a string from a pointer to a char. Used in GetSDKVersion().
        /// 从指向char的指针返回字符串。在GetSDKVersion()中使用。
        /// </summary>
        /// <param name="ptr">Pointer to a char.</param>
        /// <returns>The char as a string.</returns>
        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);
        }

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

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

        /// <summary>
        /// Gets the max FPS for each resolution setting. Higher FPS will cause lower GPU performance.
        /// 获取每个分辨率设置的最大FPS。较高的FPS将导致较低的GPU性能。
        /// Lance:后面指的是越高帧率将要求更好的GPU性能
        /// </summary>
        /// <param name="reso"></param>
        /// <returns>The resolution</returns>
        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;
        }

        /// <summary>
        /// Get a quaternion from a matrix with a minimum size of 3x3.
        /// 从最小尺寸为3x3的矩阵中获取四元数。
        /// Lance:四元素是三维旋转的另外一种数学描述    什么是四元素:https://blog.csdn.net/qq_36537774/article/details/86533999
        /// </summary>
        /// <param name="m">The matrix.</param>
        /// <returns>A quaternion which contains the matrix's rotation.</returns>。
        /// <returns>包含矩阵旋转的四元数</returns>。
        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;
        }

        /// <summary>
        /// Performs a rigid transform.
        /// 执行刚性变换。
        /// </summary>
        /// <param name="quaternion"></param> 原始角度
        /// <param name="translation"></param> 原始位置
        /// <param name="targetQuaternion"></param>  目标角度
        /// <param name="targetTranslation"></param> 目标位置
        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);
        }

        /// <summary>
        /// Checks that the ZED plugin's dependencies are installed.
        /// 检查是否已安装ZED插件的依赖项。
        /// </summary>
        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;
        }

        /// <summary>
        /// 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中显示。
        /// </summary>
        /// <returns><c>True</c>, if USB device connected was found, <c>false</c> otherwise.</returns>
        /// <param name="Device brand.">Type.</param>
        public static bool CheckUSBDeviceConnected(USB_DEVICE Type)
        {
            if (dllz_find_usb_device(Type))
                return true;
            else
                return false;
        }


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

        /// <summary>
        /// Create a camera in Live mode (input comes from a connected ZED device, not SVO playback).
        /// 在实时模式下创建相机(输入来自所连接的ZED设备,而不是SVO播放)。
        /// </summary>
        /// <param name="verbose">True to create detailed log file of SDK calls at the cost of performance.
        /// 为True会创建SDK调用的详细日志文件,但会降低性能。</param>
        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);
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            /// <summary>
            /// Copy constructor. Takes values from
            /// Unity-suited InitParameters class.
            /// 复制构造函数。从适用于Unity的InitParameters类中获取值。
            /// </summary>
            /// <param name="init"></param>
            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;
            }
        }


        /// <summary>
        /// Checks if the ZED camera is plugged in, opens it, and initializes the projection matix and command buffers for updating textures.
        /// 检查是否插入了ZED摄像机,将其打开,然后初始化投影矩阵和命令缓冲区以更新贴图。
        /// </summary>
        /// <param name="initParameters">Class with all initialization settings.
        /// A newly-instantiated InitParameters will have recommended default values
        /// 具有所有初始化设置的类。
        /// 新实例化的InitParameters将具有建议的默认值。.</param>
        /// <returns>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,则可以使用相机。其他所有代码均指示错误。</returns>
        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; //未正确启动相机
        }


        /// <summary>
        /// Fills the projection matrix with the parameters of the ZED. Needs to be called only once.
        /// This projection matrix is off-center.
        /// 用ZED的参数填充投影矩阵。只需要调用一次。
        /// 此投影矩阵偏离中心。
        /// Lance: 这个投影矩阵我还不确定是哪个坐标系到哪个坐标系的投影
        /// </summary>
        /// <param name="zFar">应该是Z方向上最远点,500应该是近似无穷远</param>
        /// <param name="zNear">Z方向上最近点</param>
        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;
        }

        /// <summary>
        /// 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.
        /// 抓取新图像,对其进行校正,然后计算视差和(可选)深度图。
        /// 通常在主循环中的单独线程中调用抓取函数。
        /// </summary><remarks>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 </remarks>
        /// <param name="runtimeParameters">Struct holding all grab parameters.保留所有抓取参数的结构体 </param>
        /// <returns>the function returns false if no problem was encountered,
        /// true otherwise.如果没有遇到问题,该函数返回false,否则返回true。</returns>
        public sl.ERROR_CODE
            Grab(ref sl.RuntimeParameters runtimeParameters) // 发现这个函数并没有返回值,说明只是从上层告知下层相机说你给我采集新的一帧数据,但是采集完的数据并没有返回过来
        {
            return (sl.ERROR_CODE) dllz_grab(CameraID, ref runtimeParameters);
        }


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

        /// <summary>
        /// Creates a file for recording the ZED's output into a .SVO or .AVI video.
        /// 创建一个文件,用于将ZED的录制输出为.SVO或.AVI视频。
        /// </summary><remarks>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设计的格式。它包含带有时间戳的视频,以及有关用于记录它的摄像机的信息。</remarks>
        /// <param name="videoFileName">Filename. Whether it ends with .svo or .avi defines its file type.文档名称。它以.svo还是.avi结尾定义其文件类型。</param>
        /// <param name="compressionMode">How much compression to use,压缩模式</param>
        /// <returns>An ERROR_CODE that defines if the file was successfully created and can be filled with images.
        /// 一个ERROR_CODE,它定义文件是否已成功创建并且可以写入图片数据。</returns>
        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);
        }


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

        /// <summary>
        /// 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将以尽可能接近的帧速率为目标。
        /// </summary>
        /// <param name="fps">New target FPS.</param>
        public void SetCameraFPS(int fps)
        {
            if (GetFpsForResolution(currentResolution) >= fps) // 当前分辨率下的最大帧率如果大于我们设置的大小
            {
                fpsMax = (uint) fps; //为什么要把最大帧率重新赋值???
            }

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

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

        /// <summary>
        /// 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.
        /// 获取视差图(以及扩展的深度图)的当前置信度阈值。
        /// 低于给定阈值的值将从深度图中删除。
        /// </summary>
        /// <returns>Filtering value between 0 and 100.</returns>
        public int GetConfidenceThreshold()
        {
            return dllz_get_confidence_threshold(CameraID);
        }

        /// <summary>
        /// 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()之后调用。
        /// </summary>
        /// <returns>Current timestamp in nanoseconds. -1 means it's is not available, such as with an .SVO file without compression.</returns>
        /// 当前时间戳(以纳秒为单位)。 -1表示它不可用,例如未压缩的.SVO文件。
        public ulong GetCameraTimeStamp()
        {
            return dllz_get_camera_timestamp(CameraID);
        }

        /// <summary>
        /// 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).
        /// 获取调用该函数时的当前时间戳。可以与相机时间戳
        /// 进行比较,因为它们具有相同的参考(计算机的开始时间)。  时间单位是纳秒
        /// </summary>
        /// <returns>The timestamp in nanoseconds.</returns>
        public ulong GetCurrentTimeStamp()
        {
            return dllz_get_current_timestamp(CameraID);
        }

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

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

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

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

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

        /// <summary>
        /// Initialize and Start the tracking functions
        /// 初始化并启动跟踪功能
        /// </summary>
        /// <param name="quat"> rotation used as initial world transform. By default it should be identity.初始化相机的时候的变换。默认情况下,它是确定的。</param>
        /// <param name="vec"> translation used as initial world transform. By default it should be identity.初始化相机的时候的位置,默认情况下,它是确定的</param>
        /// <param name="enableSpatialMemory">  (optional) define if spatial memory is enable or not.空间映射数据内存是否需要(可选)</param>
        /// <param name="areaFilePath"> (optional) file of spatial memory file that has to be loaded to relocate in the scene.(可选)必须加载才能在场景中重新定位的空间存储文件的文件。</param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// Reset tracking
        /// 重置跟踪
        /// </summary>
        /// <param name="rotation"></param>
        /// <param name="translation"></param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 重置追踪,但是附带有偏移量
        /// </summary>
        /// <param name="rotation"></param>
        /// <param name="translation"></param>
        /// <param name="rotationOffset"></param>
        /// <param name="translationOffset"></param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 计算初始的位置
        /// </summary>
        /// <param name="rotation"></param>
        /// <param name="translation"></param>
        /// <returns></returns>
        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;
        }


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

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

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

        /// <summary>
        /// Register a texture to the base
        /// 注册一个基本的纹理
        /// </summary>
        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); //添加到纹理字典里面
        }

        /// <summary>
        /// Creates or retrieves a texture of type Image. Will be updated each frame automatically.
        /// 创建或获取图像类型的纹理。将自动更新每帧。
        /// Lance:其实就是我们常说的RGB图片而已
        /// <para>Image type textures are human-viewable, but have less accuracy than measure types.</para>
        /// <para>图像类型的纹理是人类可见的,但其精度低于度量类型。</para>
        /// </summary>
        /// <remarks>
        /// 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内存。
        /// </remarks>
        /// <param name="mode">What the image shows (left RGB image, right depth image, normal map, etc.)
        /// 图像显示的内容(左RGB图像,右深度图像,法线贴图等)</param>
        /// /// <param name="resolution">Resolution of the image. Should correspond to ZED's current resolution.
        /// 图像分辨率。应符合ZED当前的分辨率。</param>
        /// <returns>Texture2D that will update each frame with the ZED SDK's output.
        /// Texture2D将使用ZED SDK的输出更新每个帧。</returns>
        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;
        }

        /// <summary>
        /// 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:这边的度量类型我一直不理解是什么类型,我估计是深度图的意思
        /// </summary>
        /// <remarks>
        /// 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内存。
        /// </remarks>
        /// <param name="mode">What the image shows (disparity, depth, confidence, etc.),图像显示的内容(视差,深度,置信度等)</param>
        /// <param name="resolution">Resolution of the image. Should correspond to ZED's current resolution.图像分辨率。应符合ZED当前的分辨率。</param>
        /// <returns>Texture2D that will update each frame with the ZED SDK's output.Texture2D将使用ZED SDK的输出更新每个帧。</returns>
        /// 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;
        }

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

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

        /// <summary>
        /// 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:也就是说当我们需要以矩阵的形式获得彩色图片数据、深度图像需要调用这个函数
        /// </summary>
        /// <param name="view">View type (left rgb, right depth, etc.)</param>
        /// <returns>New ZEDMat for an image texture of the selected view type.就是返回相应的图像矩阵ZEDMat。</returns>
        public ZEDMat RequestCopyMatFromTextureImageType(sl.VIEW view)
        {
            return new ZEDMat(dllz_get_copy_mat_texture_image_type(CameraID, (int) view));
        }

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

        /// <summary>
        /// Destroys a texture and removes its reference in the textures list.
        /// 销毁纹理并在纹理列表中删除其参考。
        /// </summary>
        /// <param name="type">Type of texture as an int (0 for Image, 1 for Measure).纹理的类型(整数)(0表示图像,1表示测量类型)。</param>
        /// <param name="option">Corresponding options enum (sl.VIEW if Image type, sl.MEASURE if Measure type) as an integer.
        /// 对应的选项枚举(如果是图像类型,则为sl.VIEW;如果是度量类型,则为sl.MEASURE),以整数形式表示。</param>
        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);
                }
            }
        }

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

                texturesRequested.Clear();
            }
        }


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

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

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

            return null;
        }

        /// <summary>
        /// Checks if a texture of a given type has already been created.
        /// 检查是否已创建给定类型的纹理。
        /// </summary>
        /// <param name="type">Type of texture as an integer (0 for Image, 1 for Measure).</param>
        /// <param name="mode">Corresponding options enum (sl.VIEW if Image type, sl.MEASURE if Measure type) as an integer.</param>
        /// <returns>True if the texture is available.</returns>
        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;
        }

        /// <summary>
        /// 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连接/带宽问题,也可能较低。
        /// </summary>
        /// <returns>The current fps,当前帧率</returns>
        public float GetCameraFPS()
        {
            return dllz_get_camera_fps(CameraID);
        }

        /// <summary>
        /// 获得相机的标定参数
        /// </summary>
        /// <param name="raw">是否是原始图像,原始图像为未矫正畸变的图像</param>
        /// <returns></returns>
        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;
        }

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

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

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

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

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


        /// <summary>
        /// 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()调用此事件。
        /// </summary>
        public void RetrieveTextures()
        {
            dllz_retrieve_textures(CameraID);
        }

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

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

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

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

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

        /// <summary>
        /// Gets the current position of the camera and state of the tracking, with an optional offset to the tracking frame.
        /// 获取摄像头的当前位置和跟踪状态,以及跟踪框的可选偏移量。
        /// </summary>
        /// <param name="rotation">Quaternion filled with the current rotation of the camera depending on its reference frame.</param>
        /// <param name="position">Vector filled with the current position of the camera depending on its reference frame.</param>
        /// <param name="targetQuaternion">Rotational offset applied to the tracking frame.</param>
        /// <param name="targetTranslation">Positional offset applied to the tracking frame.</param>
        /// <param name="referenceFrame">Reference frame for setting the rotation/position. CAMERA gives movement relative to the last pose.
        /// WORLD gives cumulative movements since tracking started.</param>
        /// <returns>State of ZED's Tracking system (off, searching, ok).</returns>
        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);
        }


        /// <summary>
        /// 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。
        /// </summary>
        /// <param name="rotation">Quaternion filled with the current rotation of the camera depending on its reference frame.</param>
        /// <param name="position">Vector filled with the current position of the camera depending on its reference frame.</param>
        /// <param name="trackingFrame">Center of the ZED for tracking purposes (left eye, center, right eye).</param>
        /// <param name="referenceFrame">Reference frame for setting the rotation/position. CAMERA gives movement relative to the last pose.
        /// WORLD gives cumulative movements since tracking started.</param>
        /// <returns>State of ZED's Tracking system (off, searching, ok).</returns>
        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);
        }

        /// <summary>
        /// Gets the current position of the camera and state of the tracking, filling a Pose struct useful for AR pass-through.
        /// 获取摄像头的当前位置和跟踪状态,填充对AR有用的Pose结构体。
        /// </summary>
        /// <param name="pose">Current pose.</param>
        /// <param name="referenceType">Reference frame for setting the rotation/position. CAMERA gives movement relative to the last pose.
        /// WORLD gives cumulative movements since tracking started.</param>
        /// <returns>State of ZED's Tracking system (off, searching, ok).</returns>
        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);
        }


        /// <summary>
        /// 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:不是很确定这是个什么东西
        /// </summary>
        /// <returns>Error code status.</returns>
        /// <param name="rotation">Prior rotation.</param>
        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;
        }

        /// <summary>
        /// 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数据的话得调用这个函数
        /// </summary>
        /// <returns>Error code status.</returns>
        /// <param name="rotation">Rotation from the IMU.</param>
        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;
        }

        /// <summary>
        /// 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),则返回错误
        /// </summary>
        /// <returns>Error code status.</returns>
        /// <param name="rotation">Rotation from the IMU.</param>
        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;
        }

        /// <summary>
        /// Converts a float array to a matrix.
        /// 将float数组转换为矩阵。
        /// </summary>
        /// <param name="m">Matrix to be filled.</param>
        /// <param name="f">Float array to be turned into a matrix.</param>
        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];
                }
            }
        }

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

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

        /// <summary>
        /// Overloaded function for CAMERA_SETTINGS.AEC_AGC_ROI (requires iRect as input)
        /// CAMERA_SETTINGS.AEC_AGC_ROI的重载函数(需要iRect作为输入)
        /// Lance: roi 是什么玩意
        /// </summary>
        /// <param name="settings"> Must be set to CAMERA_SETTINGS.AEC_AGC_ROI. Otherwise will return -1.</param>
        /// <param name="side"> defines left=0 or right=1 or both=2 sensor target</param>
        /// <param name="roi">the roi defined as a sl.Rect</param>
        /// <param name="reset">Defines if the target must be reset to full sensor</param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// Overloaded function for CAMERA_SETTINGS.AEC_AGC_ROI (requires iRect as input)
        /// CAMERA_SETTINGS.AEC_AGC_ROI的重载函数(需要iRect作为输入)
        /// </summary>
        /// <param name="settings"> Must be set to CAMERA_SETTINGS.AEC_AGC_ROI. Otherwise will return -1.</param>
        /// <param name="side"> defines left=0 or right=1 or both=2 sensor target.</param>
        /// <param name="roi"> Roi that will be filled.</param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// Reset camera settings to default
        /// 将相机设置重置为默认设置
        /// </zsummary>
        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);
        }

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

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

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

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

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

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

        /// <summary>
        /// Checks if the ZED camera is connected.
        /// 检查是否连接了ZED相机。
        /// </summary>
        /// <remarks>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。</remarks>
        /// <returns>True if ZED is connected.</returns>
        public static bool IsZedConnected()
        {
            return Convert.ToBoolean(dllz_is_zed_connected());
        }

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

        /// <summary>
        /// Checks if the camera has been initialized and the plugin has been loaded. Throws exceptions otherwise.
        /// 检查相机是否已初始化以及插件是否已加载。否则抛出异常。
        /// </summary>
        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.");
        }

        /// <summary>
        /// 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采集了新的图片,然后才能更新纹理
        /// </summary>
        public void UpdateTextures()
        {
            GL.IssuePluginEvent(GetRenderEventFunc(), 1); //这个函数还是不大懂
        }


        / SINGLE PIXEL UTILITY FUNCTIONS 
        /// 单一像素操作,这部分对我们来说比较有用
        /// <summary>
        /// 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:这边指的是获取电脑屏幕上某个点的深度数据,如果我们获取的图片与电脑屏幕没有对齐的话,可能会发生错误
        /// <param name="position">The pixel's screen space coordinates as a Vector3.
        /// The Z component is unused - designed to take input from Input.mousePosition.
        /// 这里的参数是三维的向量,但是实际上在Z维度上是不起作用的,实际上就是图像坐标</param>
        /// <returns>Depth value as a float.  浮点类型的深度值</returns>
        /// </summary>
        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;
        }

        /// <summary>
        /// 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图像不能填满整个屏幕,则可能会导致错误。
        /// <param name="pixel">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获取输入。</param>
        /// <returns>Distance as a float.</returns>
        /// Lance:这边的输入是电脑屏幕上的像素坐标,不是图像上的像素坐标
        /// </summary>
        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);
        }

        /// <summary>
        /// Gets the position of a camera-space pixel relative to the camera frame.
        /// 获得相机空间下的位置, 和 camera frame相关 。
        /// <param name="pixel">The pixel's screen space coordinates as a Vector3. //电脑屏幕的图象坐标
        /// The Z component is unused - designed to take input from Input.mousePosition.</param>
        /// <param name="xyz">Position relative to the camera.相机空间下的坐标</param>
        /// <returns>True if successful.</returns>
        /// Lance:这个是我们需要的,就是获得某个点云点,但是有一个问题就是,这边的输入是屏幕坐标
        /// </summary>
        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;
        }


        /// <summary>
        /// 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包含此函数的高级版本,这些版本更易于使用。
        /// <param name="pixel">The pixel's screen space coordinates as a Vector3.
        /// The Z component is unused - designed to take input from Input.mousePosition.</param>
        /// <param name="normal">Normal value of the pixel as a Vector4.注意这边是一个四维向量</param>
        /// <returns>True if successful.</returns>
        /// </summary>
        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;
        }

        /// <summary>
        /// Initializes and begins the spatial mapping processes.
        /// 初始化并开始空间映射过程
        /// </summary>
        /// <param name="resolution_meter">Spatial mapping resolution in meters.空间映射分辨率,以米为单位。</param>
        /// <param name="max_range_meter">Maximum scanning range in meters.最大扫描范围,以米为单位。</param>
        /// <param name="saveTexture">True to scan surface textures in addition to geometry.除几何图形外,还适用于扫描表面纹理。</param>
        /// <returns></returns>
        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;
        }

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

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

        /// <summary>
        /// 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)。
        /// </summary>
        /// <param name="vertices">Vertices of the mesh.</param>
        /// <param name="triangles">Triangles, formatted as the index of each triangle's three vertices in the vertices array.</param>
        /// <param name="nbSubmeshMax">Maximum number of submeshes that can be handled.</param>
        /// <returns>Error code indicating if the retrieval was successful, and why it wasn't otherwise.</returns>
        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);
        }

        /// <summary>
        /// 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每次完成应用最后一个网格更新时都会调用此方法。
        /// </summary>
        public void RequestMesh()
        {
            dllz_request_mesh_async(CameraID);
        }

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

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

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

        /// <summary>
        /// Loads a saved mesh file. ZEDSpatialMapping then configures itself as if the loaded mesh was just scanned.
        /// 加载保存的网格文件。然后,ZEDSpatialMapping将自身配置为就像刚刚扫描加载的网格一样。
        /// </summary>
        /// <param name="filename">Path and filename of the mesh. Should include the extension (.obj, .ply or .bin).</param>
        /// <param name="nbVerticesInSubmeshes">Array of the number of vertices in each submesh.</param>
        /// <param name="nbTrianglesInSubmeshes">Array of the number of triangles in each submesh.</param>
        /// <param name="nbSubmeshes">Number of submeshes.</param>
        /// <param name="updatedIndices">List of all submeshes updated since the last update.</param>
        /// <param name="nbVertices">Total number of updated vertices in all submeshes.</param>
        /// <param name="nbTriangles">Total number of updated triangles in all submeshes.</param>
        /// <param name="nbSubmeshMax">Maximum number of submeshes that can be handled.</param>
        /// <param name="textureSize">Array containing the sizes of all the textures (width, height) if applicable.</param>
        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);
        }

        /// <summary>
        /// Filters a mesh to remove triangles while still preserving its overall shape (though less accurate).
        /// 过滤网格以删除三角形,同时仍保留其总体形状(尽管精度较低)。
        /// Lance:大概的意思就是一些网格可能是在同一个平面上的,那么就可以结合在一起,减少网格的定点数,
        /// </summary>
        /// <param name="filterParameters">Filter level. Higher settings remove more triangles.</param>
        /// <param name="nbVerticesInSubmeshes">Array of the number of vertices in each submesh.</param>
        /// <param name="nbTrianglesInSubmeshes">Array of the number of triangles in each submesh.</param>
        /// <param name="nbSubmeshes">Number of submeshes.</param>
        /// <param name="updatedIndices">List of all submeshes updated since the last update.</param>
        /// <param name="nbVertices">Total number of updated vertices in all submeshes.</param>
        /// <param name="nbTriangles">Total number of updated triangles in all submeshes.</param>
        /// <param name="nbSubmeshMax">Maximum number of submeshes that can be handled.</param>
        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);
        }

        /// <summary>
        /// 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:这部分内容还需要理解一下
        /// </summary>
        /// <param name="nbVerticesInSubmeshes">Array of the number of vertices in each submesh.</param>
        /// <param name="nbTrianglesInSubmeshes">Array of the number of triangles in each submesh.</param>
        /// <param name="nbSubmeshes">Number of submeshes.</param>
        /// <param name="updatedIndices">List of all submeshes updated since the last update.</param>
        /// <param name="nbVertices">Total number of updated vertices in all submeshes.</param>
        /// <param name="nbTriangles">Total number of updated triangles in all submeshes.</param>
        /// <param name="textureSize"> Vector containing the size of all the texture (width, height). </param>
        /// <param name="nbSubmeshMax">Maximum number of submeshes that can be handled.</param>
        /// <returns></returns>
        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);
        }

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

        /// <summary>
        /// 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自动可以检测到重力方向
        /// </summary>
        /// <returns>Vector3 pointing downward.</returns>
        public Vector3 GetGravityEstimate()
        {
            Vector3 v = Vector3.zero;
            dllz_spatial_mapping_get_gravity_estimation(CameraID, ref v);
            return v;
        }

        /// <summary>
        /// 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).
        /// 合并扫描中的块。这用于将许多小网格(对扫描过程有效)
        /// 变成几个大网格(使用起来更方便)。
        /// </summary>
        /// <param name="numberFaces"></param>
        /// <param name="nbVerticesInSubmeshes">Array of the number of vertices in each submesh.</param>
        /// <param name="nbTrianglesInSubmeshes">Array of the number of triangles in each submesh.</param>
        /// <param name="nbSubmeshes">Number of submeshes.</param>
        /// <param name="updatedIndices">List of all submeshes updated since the last update.</param>
        /// <param name="nbVertices">Total number of updated vertices in all submeshes.</param>
        /// <param name="nbTriangles">Total number of updated triangles in all submeshes.</param>
        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);
        }

        /// <summary>
        /// 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:这个函数就是用来获取点云和实际深度数据的
        /// </summary><remarks>
        /// 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
        /// </remarks>
        /// <param name="mat">ZEDMat to fill with the new texture.</param>
        /// <param name="measure">Measure type (depth, confidence, xyz, etc.)</param>
        /// <param name="mem">Whether the image should be on CPU or GPU memory.</param>
        /// <param name="resolution">Resolution of the texture.</param>
        /// <returns>Error code indicating if the retrieval was successful, and why it wasn't otherwise.</returns>
        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));
        }

        /// <summary>
        /// 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:只能用于彩色图象和深度图象, 不能用于置信度矩阵或者精确的深度数据
        /// </summary><remarks>
        /// 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
        /// </remarks>
        /// <param name="mat">ZEDMat to fill with the new texture.</param>
        /// <param name="view">Image type (left RGB, right depth map, etc.)</param>
        /// <param name="mem">Whether the image should be on CPU or GPU memory.</param>
        /// <param name="resolution">Resolution of the texture.</param>
        /// <returns>Error code indicating if the retrieval was successful, and why it wasn't otherwise.</returns>
        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));
        }

        /// <summary>
        /// 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。
        /// </summary>
        /// <param name="planeDistance">Distance from a camera in the ZED rig to the quad/Canvas object holding the ZED image.
        /// ZED的摄影机到包含ZED图像的Quad / Canvas对象的距离。</param>
        /// <returns></returns>
        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  ///
        


        /// <summary>
        /// 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的更高版本。
        /// </summary>
        /// <param name="plane">Data on the detected plane.</param>
        /// <param name="playerHeight">Height of the camera from the newly-detected floor.</param>
        /// <param name="priorQuat">Prior rotation.</param>
        /// <param name="priorTrans">Prior position.</param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 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.
        /// 使用来自检测到的地板平面的数据,使用更新提供的顶点和三角形阵列,以制作表示它的网格。这些数组直接从包装器更新。
        /// </summary>
        /// <param name="vertices">Array to be filled with mesh vertices.</param>
        /// <param name="triangles">Array to be filled with mesh triangles, stored as indexes of each triangle's points.</param>
        /// <param name="numVertices">Total vertices in the mesh.</param>
        /// <param name="numTriangles">Total triangle indexes (3x number of triangles).</param>
        /// <returns></returns>
        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);
        }

        /// <summary>
        /// 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的更高版本。
        /// </summary>
        /// <param name="plane">Data on the detected plane.检测平面上的数据。</param>
        /// <param name="screenPos">Point on the ZED image to check for a plane.在ZED图像上指向以检查平面。</param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 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中被调用一次
        /// </summary>
        /// <param name="vertices">Array to be filled with mesh vertices.要用网格顶点填充的数组</param>。
        /// <param name="triangles">Array to be filled with mesh triangles, stored as indexes of each triangle's points.用网格三角形填充的数组,存储为每个三角形点的索引。</param>
        /// <param name="numVertices">Total vertices in the mesh.网格中的总顶点。</param>
        /// <param name="numTriangles">Total triangle indexes (3x number of triangles).三角形索引总数(三角形的3倍)。</param>
        /// <returns></returns>
        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 ///
        

        /// <summary>
        /// Creates an streaming pipeline.
        /// 创建一个流管道
        /// </summary>
        /// <params>
        /// Streaming parameters: See sl::StreamingParameters of ZED SDK. See ZED SDK API doc for more informations
        /// </params>
        /// <returns>An ERROR_CODE that defines if the streaming pipe was successfully created
        /// 一个ERROR_CODE,定义是否成功创建了流管道</returns>
        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);
        }

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

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


        
        /// Save utils fct   ///
        

        /// <summary>
        /// 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结尾
        /// </summary>
        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;
        }

        /// <summary>
        /// Save the current depth in a file defined by filename.
        /// Supported formats are PNG,PFM and PGM
        /// 将当前深度保存在filename定义的文件中。
        /// 支持的格式为PNG,PFM和PGM
        /// </summary>
        /// <param name="side"> defines left (0) or right (1) depth</param>
        /// <param name="filename"> filename must end with .png, .pfm or .pgm</param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 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插件里面第一次看到点云的概念啊
        /// </summary>
        /// <param name="side">defines left (0) or right (1) point cloud,哪一边相机的点云</param>
        /// <param name="filename"> filename must end with .ply, .xyz , .vtk or .pcd </param>
        /// <returns></returns>
        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 ///
        

        /// <summary>
        /// Enable object detection module
        /// 启用对象检测模块
        /// </summary>
        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;
        }

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

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

        /// <summary>
        /// Retrieve object detection data
        /// 检索物体检测数据
        /// </summary>
        /// <param name="od_params"> Object detection runtime parameters,
        /// 对象检测运行时参数</param>
        /// <param name="objFrame"> ObjectsFrameSDK that contains all the detection data,
        /// 包含所有检测数据的ObjectsFrameSDK</param>
        /// <returns></returns>
        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
    
 

本文链接: http://www.dtmao.cc/news_show_150350.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?