OpenTK---空间中单个三维点的绘制

2023-11-12

OpenTK是一个跨平台的包,可以让我们能够使用C#来调用OpenGL来进行三维可视化的开发。

因为这是第一篇,所以会写的比较详细,后面重复用到的内容就不再二次说明了。

  1. 创建主程序中的类:
using OpenTK.Mathematics;
using OpenTK.Windowing.Desktop;

namespace OpenTK_SelfMadeBasis
{
    class Program
    {
        static void Main(string[] args)
        {
            // 其中根据c#语言特性,第一个NativeWindowSettings也可以用var替换
            NativeWindowSettings nativeWindowSettings = new NativeWindowSettings()
            {
                // 通常用Vector2i就可以了,设定window尺寸
                Size = new Vector2i(800, 600),
                Title = "Draw Single Line",
            };
            // 启动主程序
            using (Window window = new Window(GameWindowSettings.Default, nativeWindowSettings))
            {
                window.Run();
            }
        }
    }
}

其中NativeWindowSettingsOpenTK.Windowing.Desktop域名下的内容,因此在程序的开头,我们需要使用using OpenTK.Windowing.Desktop;来对该域名进行引用。此外,函数Vector2i()OpenTK.Mathematics域名下的函数,因此同样在开头我们要使用using OpenTK.Mathematics;对该域名进行引用。函数Vector2i(x, y)可以定义一个二维向量,我们通过将这个二维向量赋值给NativeWindowSettings下的默认Size属性可以实现对我们对之后绘图使用的GUI窗口大小的调整。同理,给默认Title属性传递一个字符串可以实现对绘图使用的GUI窗口的名称的调整。上述的代码基本可以说是固定的格式,唯一需要改动的也只有窗口的尺寸和名称,其余部分均可保持不变。

  1. 构建主程序中调用的GUI窗口界面的类
using OpenTK_SelfMadeBasis.Common;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.GraphicsLibraryFramework;
using OpenTK.Windowing.Desktop;

// 使用EBO控制要绘制的点,使用DrawArrays方法绘制单个点,这种方法不需要EBO
namespace OpenTK_SelfMadeBasis
{
	// 创建的GUI窗口类是从OpenTK中定义的GameWindow类中继承的
    public class Window : GameWindow
    {
        // 设定所需要绘制点的坐标,因为是3维中的点,因此一个点需要具有三个坐标(x, y, z)
        private readonly float[] _vertices =
        {
            -0.5f, -0.5f, 0.0f,
        };
		
		// 创建一个Vertex Buffer Object(VBO)的句柄
        private int _vertexBufferObject;    
			
		// 创建一个Vertex Array Object(VAO)的句柄
        private int _vertexArrayObject;
		
		// 创建一个Shader(着色器)的句柄
        private Shader _shader;

		// 这里是一个构造函数
        public Window(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings)
            : base(gameWindowSettings, nativeWindowSettings)
        {
        }

        // OnLoad:OpenGL初始化函数
        protected override void OnLoad()
        {
        	// 设定清除屏幕后屏幕显示的背景色,这里是深绿色
            GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
			
			// 创建一个缓冲区,GL.GenBuffer()会返回一个句柄,这个句柄在之前我们已经声明过了
            _vertexBufferObject = GL.GenBuffer();
	
			// 将创建的缓冲区句柄和目标缓冲区ArrayBuffer绑定起来,之后通过句柄_vertexBufferObject可以实现对ArrayBuffer的操作
            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject);
			
			// 上传之前定义的端点值到缓冲区
            GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw);
			
			// Gen的意思是generate(产生),这里生成一个VAO用来告知计算机如何分割和处理之前上传的数据
            _vertexArrayObject = GL.GenVertexArray();
            // 将VAO与VertextArray进行绑定,以后通过_vertexArrayObject句柄来对VertexArray进行操作
            GL.BindVertexArray(_vertexArrayObject);

			// 定义Shader(着色器)如何处理VBO数据
            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);
            GL.EnableVertexAttribArray(0);

			// 初始化着色器
            _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");

			// 激活着色器
            _shader.Use();  
            base.OnLoad();
            // 注意:VAO和着色器都是全局的
        }

        // OnRenderFrame:OpenGL绘制图像函数
        protected override void OnRenderFrame(FrameEventArgs e)
        {
        	// 清屏
            GL.Clear(ClearBufferMask.ColorBufferBit);   
			
			// 调用着色器
            _shader.Use();  
			
			// 调用VAO
            GL.BindVertexArray(_vertexArrayObject); 

			// 绘制ArrayBuffer中接收到的数据
            GL.DrawArrays(PrimitiveType.Points, 0, 1);
	
			// 交换缓冲区,防止程序运行异常
            SwapBuffers();  

            base.OnRenderFrame(e);
        }
		// OnUpdateFrame: 更新窗口函数
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            var input = KeyboardState;

			// 当按下Esc键后关闭GUI窗口
            if (input.IsKeyDown(Keys.Escape))
            {
                Close();
            }

            base.OnUpdateFrame(e);
        }
        // OnResize: OpenGL窗口尺寸调整函数
        protected override void OnResize(ResizeEventArgs e)
        {
            // 当我们调整窗口尺寸的时候,相应的物体坐标也跟着调整
            GL.Viewport(0, 0, Size.X, Size.Y);
            base.OnResize(e);
        }

        // OnUnload: OpenGL使用后回收资源函数
        protected override void OnUnload()
        {
        	// 取消所有对象的绑定
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
            GL.BindVertexArray(0);
            GL.UseProgram(0);

            // 删除所有的缓冲资源
            GL.DeleteBuffer(_vertexBufferObject);
            GL.DeleteVertexArray(_vertexArrayObject);
            GL.DeleteProgram(_shader.Handle);
            
            base.OnUnload();
        }
    }
}

GameWindow是包含在域名OpenTK.Windowing.Desktop中的,因此在开头需要对该域名进行引用。

  1. 着色器类
    我们可以看到在上面的窗口类中,我们在开头引用了一个OpenTK_SelfMadeBasis.Common;域名,这个实际上是一个着色器类,因为着色器类对于我们以后的所有工程都是通用的,所以将其存放在原始域名.Common的新域名下。
using System;
using System.IO;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;


namespace OpenTK_Tutorials.Common
{
    // 着色器类
    public class Shader
    {
    	// 定义(声明)一个只读的句柄
        public readonly int Handle;

		// 定义一个只读的字典
        private readonly Dictionary<string, int> _uniformLocations;

        // 这里介绍如何创建一个着色器
        // 着色器是用 GLSL 编写的,这是一种在语义上与 C 非常相似的语言。
        public Shader(string vertPath, string fragPath)
        {
            // 加载端点着色器并编译
            var shaderSource = File.ReadAllText(vertPath);

            // 创建一个VertexShader类型的着色器
            var vertexShader = GL.CreateShader(ShaderType.VertexShader);

            // 将GLSL原代码和端点着色器绑定
            GL.ShaderSource(vertexShader, shaderSource);

            // 编译端点着色器
            CompileShader(vertexShader);

            // 对片段着色器做同样的事情
            shaderSource = File.ReadAllText(fragPath);
            var fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
            GL.ShaderSource(fragmentShader, shaderSource);
            CompileShader(fragmentShader);

            // 必须将这两个着色器放入OpenGL能够执行的程序中
            // 创建一个程序
            Handle = GL.CreateProgram();

            // 将两个着色器都与之绑定
            GL.AttachShader(Handle, vertexShader);
            GL.AttachShader(Handle, fragmentShader);

            // 然后将他们两个关联起来
            LinkProgram(Handle);

            // 当程序被链接并编译以后,着色器相应的代码就被复制到了程序中,单个的着色器就不再被需要了,将着色器与程序分离,并删除他们
            GL.DetachShader(Handle, vertexShader);
            GL.DetachShader(Handle, fragmentShader);
            GL.DeleteShader(fragmentShader);
            GL.DeleteShader(vertexShader);

            // 获取活动的全局着色器(uniforms)数量
            GL.GetProgram(Handle, GetProgramParameterName.ActiveUniforms, out var numberOfUniforms);

            // 分配字典来保存位置
            _uniformLocations = new Dictionary<string, int>();

            // 遍历所有全局着色器
            for (var i = 0; i < numberOfUniforms; i++)
            {
                // 获取全局着色器的名字
                var key = GL.GetActiveUniform(Handle, i, out _, out _);

                // 获取位置
                var location = GL.GetUniformLocation(Handle, key);

                // 将它添加到字典中
                _uniformLocations.Add(key, location);
            }
        }

        private static void CompileShader(int shader)
        {
            // 编译着色器
            GL.CompileShader(shader);

            // 检查是否存在编译错误
            GL.GetShader(shader, ShaderParameter.CompileStatus, out var code);
            if (code != (int)All.True)
            {
                // 使用GL.GetShaderInfoLog(shader)函数来获取作物的详细信息
                var infoLog = GL.GetShaderInfoLog(shader);
                throw new Exception($"Error occurred whilst compiling Shader({shader}).\n\n{infoLog}");
            }
        }

        private static void LinkProgram(int program)
        {
            // 链接程序
            GL.LinkProgram(program);

            // 检查错误
            GL.GetProgram(program, GetProgramParameterName.LinkStatus, out var code);
            if (code != (int)All.True)
            {
                throw new Exception($"Error occurred whilst linking Program({program})");
            }
        }

        // 启动着色器程序的封装函数
        public void Use()
        {
            GL.UseProgram(Handle);
        }
        
        public int GetAttribLocation(string attribName)
        {
            return GL.GetAttribLocation(Handle, attribName);
        }

        public void SetInt(string name, int data)
        {
            GL.UseProgram(Handle);
            GL.Uniform1(_uniformLocations[name], data);
        }

        public void SetFloat(string name, float data)
        {
            GL.UseProgram(Handle);
            GL.Uniform1(_uniformLocations[name], data);
        }

        public void SetMatrix4(string name, Matrix4 data)
        {
            GL.UseProgram(Handle);
            GL.UniformMatrix4(_uniformLocations[name], true, ref data);
        }

        public void SetVector3(string name, Vector3 data)
        {
            GL.UseProgram(Handle);
            GL.Uniform3(_uniformLocations[name], data);
        }
    }
}

下面介绍端点着色器和片段着色器的GLSL写法。

  1. 端点着色器
// 告诉应该使用哪个版本的GLSL编译器
#version 330 core

// in 表示输入量
// vec3表示是一个三维向量
// aPosition是这个三维向量的名称
layout(location = 0) in vec3 aPosition;

// 将三维端点值传入即可,1.0表示另一个高级参数,这里不做过多解释,取1.0,也可以省略
void main(void)
{
    gl_Position = vec4(aPosition, 1.0);
}
  1. 片段着色器
#version 330

// 声明一个输出的四维向量outputColor
out vec4 outputColor;

void main()
{
	// 设定输出的颜色,分别对应RGBA值
    outputColor = vec4(1.0, 1.0, 0.0, 1.0);
}

我们可以看到上面使用了许多句柄,所谓句柄,简单地说就是一个变量,通过这个变量可以实现对特定对象的访问。

对于端点和片段着色器,我们需要将它们放在C:\....\OpenTK_SelfMadeBasis\DrawSinglePoints\bin\Debug\netcoreapp3.1\Shaders目录下才行,其中C:\....\OpenTK_SelfMadeBasis\DrawSinglePoints表示我们创建的工程目录,并且这两个着色器的后缀名如下图所示。
在这里插入图片描述
注意:上述着色器代码中的注释是中文给出的,是为了方便大家理解着色器代码,当大家复制代码后,应该删除掉中文注释,着色器内部的代码不能用中文注释,否则会报错,但是可以使用英文进行注释。

运行程序可以得到下面的结果:
在这里插入图片描述

至此,我们就完成了单个三维点在空间中的绘图表示。重要是通过这个示例来展示基础的OpenTK操作框架。之后我们会进行真实的三维图形的绘制。

关于上述的四个类文件如何配置,请看这篇Visual Studio内配置OpenTK环境(超链接点击跳转)。

码字不易,如果大家觉得有用,请高抬贵手给一个赞让我上推荐让更多的人看到吧~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenTK---空间中单个三维点的绘制 的相关文章

  • 部署 MVC4 项目时出错:找不到文件或程序集

    过去 我只需使用 Visual Studio 2012 发布到 AWS 菜单项即可部署我的 MVC4 网站 到 AWS Elastic Beanstalk 现在 程序可以在本地编译并运行 但无法部署 从消息来看 它似乎正在寻找不在当前部署的
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • MongoDB的使用

    MongoDB 是一个跨平台的 以 JSON 为数据模型的文档数据库 是当前 NoSQL 数据库产品中最热门的一种 它介于关系数据库和非关系数据库之间 是非关系数据库当中功能最丰富 最像关系数据库的产品 1 MongoDB 与 MySQL
  • 使用DVD光盘或者ISO作为本地YUM源

    Yum 全称为 Yellow dog Updater Modified 是一个在 Fedora RedHat CentOS 中的 Shell 前端软件包管理器 基于 RPM 包管理 能够从指定的服务器自动下载 RPM 包并且安装 可以自动处
  • 摸爬滚打DirectX11_day01——VS2015与DirectX11的配置

    什么是DirectX11 DirectX 微软提供的应用程序接口集 APIs 被设计为在运行 windows 操作系统平台上用来提供给开发人员控制硬件的底层接口 它的各个组件提供了访问不同硬件的能力 包括图形 显卡 声音 声卡 GPU 输入
  • 数据库原理(二 )

    文章目录 一 关系模型有关概念 二 关系的类型和性子 2 1 类型 2 2 基本关系的六条性质 三 E R图转换为关系模型的方法 3 1 实体联系 1 1 3 2 实体联系 1 n 方法一 方法 二 3 3 联系实体 m n 四 关系模型的
  • 官方AI语音系统电销机器人系统搭建

    端是VUE后端是java还有CC 4台服务器组成nginx kafka mysql数据库 fs 支持大并发 通话录音存储七牛云可以自定义录音存储时长不用担心录音多影响系统硬盘存储空间可自定义删除录音存留时间 市面上的都是单服务器然后加挂大数
  • 以太坊智能合约教程(一)搭建以太坊私有链搭建

    环境说明 win10 64位 geth1 6 5 1 安装geth 安装完成以后 先创建2个账号 geth account new 然后建立 mygenesis json nonce 0x0000000000000042 difficult
  • 更改SVN的用户名、密码等信息的两种方式

    一 背景 在刚入职一家公司的时候 经常会去安装一些版本管理工具 例如 git或者svn 下面就拿svn来举例 假如你拿到的电脑是上位同事留下的 里面的记录并没有被完全清空 当你安装好svn 大概率还是会使用上一位同事的配置文件 那在此之后你
  • Verilog HDL FPGA 从入门到放弃(1)

    这是一篇入门文章 笔者也曾经迷茫过 也很困惑过 硬件编程是怎么样的 但是功夫不负有心人 希望我的文章获得读者的认同 谦虚使人进步 希望不足之处请提意见 对于有意思的东西大家可以探讨一下 硬件编程verilog 建模 一个简单的模型 流水灯的
  • 使用Spring Boot和EasyExcel的导入导出

    在当今信息化社会 数据的导入和导出在各种业务场景中变得越来越重要 为了满足复杂的导入导出需求 结合Java编程语言 Spring Boot框架以及EasyExcel库 我们可以轻松地构建出强大而灵活的数据处理系统 本文将引导您通过一个案例学
  • Odoo(OpenERP)补货规则笔记整理 - 草稿

    感谢Jeffery Jason ccdos roson 等人分享讨论 推式规则 移库规则 从一个库位推送到另一个库位 拉式规则 补货规则 包括生产 采购 移动 进行仓库设置时 会自动创建默认的拉式规则 最小库存规则 再订货规则 补货 某个库
  • iphone 服务器未响应,iPhone 死机没反应?先试试这些方法!

    iPhone 突然死机了 相信很多果粉都遇过这种情况 通常在手机死机的时候 无论我们怎么点屏幕都没反应 如果在一些紧急情况下发生死机 是很头疼的一件事 那么 iPhone 死机没反应 我们到底应该怎么处理呢 今天 疯师傅教你们三招 自己在家
  • 静态类型

    从程序运行或者二进制的角度 或者说 运行时 的角度来看 静态类型就是 没有类型 因为程序实际上不在运行时保存任何的静态类型 这也是静态类型又被称为 编译时类型 的原因 因为一旦经过编译 静态类型系统就基本上消失殆尽了 为什么又说基本上了呢
  • freemarker+itext5实现用模板方式,导出word和pdf(spring-boot直接可使用)

    第一步 需要引入的jar包
  • PHP$_FILES原生图片上传

    PHP FILES原生图片上传 if empty FILES file name header Content type text html charset utf 8 if FILES file error 0 判断上传是否正确 file
  • 接口自动化测试框架-Python+Requests+Yaml

    零代码极限封装的 接口自动化测试框架 目前已经完全能够实现真正的零代码落地并在企业中推广 其中用到的最核心的封装技术如下 核心技术 1 热加载封装 是全网最早应用于自动化测试框架的封装技术 2 Requests统一请求封装 3 接口关联封装
  • windows下Qt、MinGW、libmodbus源码方式的移植与使用

    windows下Qt MinGW libmodbus源码方式的移植与使用 1 前言 libmodbus官网 https libmodbus org github下载 https github com stephane libmodbus 截
  • element-ui 源码解析,你知道 v-loading 是如何实现的吗?

    前言 相信大家肯定都用过 element ui 里面的 v loading 来写加载 但是如果让你来写一个的话你会怎么写呢 众所周知 element ui 框架的 v loading 有两种使用方式 一种是在需要 loading 的标签上直
  • Yolov5目标检测环境搭建过程(Cuda+Pytorch+Yolov5)

    本文介绍了如何搭建yolov5目标检测代码的环境 详细记录了python虚拟环境 安装pytorch 加载yolov5项目以及运行检测程序的全过程 完成了本文的yolov5项目搭建后 可以查看本文下一篇文章 使用yolov5训练自己的数据集
  • chown、chmod详解

    首先通过ll命令查看目录下文件 主要看最前面一列 我把 drwxr xr x 拿出来说 d 目录 文件类型 rwx 可读 可写 可执行 2 4位 所属者权限 r x 可读 可执行 5 7位 所属组权限 r x 可读 可执行 8 10位 其它
  • OpenTK---空间中单个三维点的绘制

    OpenTK是一个跨平台的包 可以让我们能够使用C 来调用OpenGL来进行三维可视化的开发 因为这是第一篇 所以会写的比较详细 后面重复用到的内容就不再二次说明了 创建主程序中的类 using OpenTK Mathematics usi