NURBS

article/2025/8/21 9:32:01

非均匀有理样条NURBS( Non-Uniform Rational B-Splines ) 是近年来发展迅速,应用广泛的一种表示曲线曲面造型技术。它能够精确地表示二次规则曲线曲面,从而能用统一的数学形式表示规则曲面与自由曲面,具有可影响曲线曲面形状的权因子,使形状更宜于控制和实现。1991 年国际标准化组织颁布了关于工业产品数据交换的STEP 国际标准,将NURBS 方法作为定义工业产品几何形状的唯一数学描述方法,从而使NURBS 方法成为曲面造型技术发展趋势中最重要的基础。 

OpenGLNURBS 的支持是通过实用库实现的,相应的函数有

gluNewNurbsRenderer

gluNurbsProperty

gluNurbsSurface

gluBeginSurface

gluEndSurface

gluDeleteNurbsRenderer

 

创建NURBS 曲面时,首先使用gluNewNurbsRenderer 创建一个NURBS 对象,然后使用gluNurbsProperty 设置NURBS 对象的属性。gluBeginSurface~gluEndSurface 的作用类似glBegin~glEnd ,在两个函数间使用 gluNurbsSurface 来定义NURBS 曲面的具体形状。gluEndSurface 完成了NURBS 曲面的定义后就可以显示了。需要注意的是,不再使用NURBS 对象时,要记得使用 gluDeleteNurbsRenderer 释放掉其对象所占用的内存。

gluNewNurbsRenderer 函数不带任何参数,调用成功后返回一个GLUnurbsObj 类型的指针,指向创建成功的NURBS 对象。其原型如下

 

GLUnurbsObj* gluNewNurbsRenderer( 
void );


 

创建NURBS 对象的代码类似如下

 

GLUnurbsObj *theNurb;

theNurb = gluNewNurbsRenderer();


 

接下来,要使用 gluNurbsProperty 来设置theNurb 的属性。gluNurbsProperty 的原型如下

 

void gluNurbsProperty(

  
GLUnurbsObj *
nobj
,

  
GLenum
 property
,

  
GLfloat
 value

);

nobj 参数就是使用gluNewNurbsRenderer 创建的NURBS 对象。property 是需要设置的属性,可以取的值如下表10-2 所示。

 

10-2   gluNurbsProperty 参数含义

Property 取值

含义

GLU_SAMPLING_TOLERANCE

当抽样方法设置为GLU_PATH_LENGTH 时指定抽样误差,单位是像素。缺省值为50.0

GLU_DISPLAY_MODE

使用value 参数来定义NURBS 曲面的渲染方式,此时value 可以取值GLU_FILLGLU_OUTLINE_POLYGONGLU_OUTLINE_PATCH

GLU_FILL 表示曲面填充多边形方式渲染,曲面是一个整体的平滑曲面,这也是缺省的方式。

GLU_OUTLINE_POLYGON 表示曲面仅仅画出由小方格组成的外轮廓,表现出来的就是网格曲面。

GLU_OUTLINE_PATCH 则纯粹是一个外轮廓边沿。

GLU_CULLING

value 参数是一个BOOL 型的数值,确定NURBS 曲线是否丢弃视点范围之外的控制点,缺省为GL_FALSE

GLU_AUTO_LOAD_MATRIX

value 参数是一个BOOL 型的数值。当为GL_TRUE 时,表示NURBS 要从OpenGL 服务器下载投影矩阵,模型观察矩阵和视点来计算对每一个NURBS 曲线计算抽样和消隐矩阵。当valueGL_FALSE 时,表示必须由本地应用提供投影矩阵,模型观察矩阵和视点。对于非网络应用来说,该项可以忽略。

GLU_PARAMETRIC_TOLERANCE

当抽样方法为GLU_PARAMETRIC_ERROR 时指定最大距离,单位是像素,缺省值为0.5

GLU_SAMPLING_METHOD

指定怎样利用方格拼成NURBS 曲面,即拟合NURBS 的方法。对应的value 可以取GLU_PATH_LENGTHGLU_PARAMETRIC_ERRORGLU_DOMAIN_DISTANCE

value 取值为GLU_PATH_LENGTH (缺省值)时,用于组成曲面的小方格的边长最大不超过以GLU_SAMPLING_TOLERANCE 设置的值。

value 取值为GLU_PARAMETRIC_ERROR 时,以 GLU_PARAMETRIC_TOLERANCE 指定的最大距离值在小方格和整个表面之间。

value 取值为 GLU_DOMAIN_DISTANCE 时,指明在uv 方向上每单位长度有多少个抽样点。

GLU_U_STEP

指定沿u 方向每单位长度的采样点数,当LU_SAMPLING_METHOD 设置成GLU_DOMAIN_DISTANCE GLU_U_STEP 有效。缺省为100

GLU_V_STEP

指定沿v 方向每单位长度的采样点数,当LU_SAMPLING_METHOD 设置成GLU_DOMAIN_DISTANCE GLU_U_STEP 有效。缺省为100

 

value 表示property 的值,它可以是一个数字,也可以是GLU_PATH_LENGTH GLU_PARAMETRIC_ERRORGLU_DOMAIN_DISTANCE 三者之一。

 

下面是一个NURBS 曲面的生成代码。

 

//NURBS 对象

GLUnurbsObj *theNurb;

 

// 三种显示模式

GLfloat DisplayMode[3] = {GLU_FILL, GLU_OUTLINE_POLYGON, GLU_OUTLINE_PATCH};

int Mode = 0;                   // 缺省的显示模式为GLU_FILL

BOOL bModePressed = FALSE;  // 改变显示模式选择按键

 

// 改变显示模式的按键处理在WndProc

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_ACTIVATE:

    ……   

    case WM_SIZE:

        ……

    case WM_KEYDOWN:

        switch(wParam)

        {

        case VK_ESCAPE:

            PostQuitMessage(0);

            return 0;

        case VK_SPACE:              // 空格键进行显示模式切换

            bModePressed = TRUE;

            Mode ++;

            if(Mode >2)

                Mode = 0;

            break;

        }

        break;

        case WM_DESTROY:

            PostQuitMessage(0);

            break;

        default:

            return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

 

glInit() 中,我们来建立一个光源,并且创建一种材质,将其应用到NURBS 曲面上。

 

int glInit()

{

   

    // 启用阴影平滑(Smooth Shading)

    glShadeModel(GL_SMOOTH);

 

    // 设置深度缓冲

    glClearDepth(1.0f);

 

    // 启动深度测试

    glEnable(GL_DEPTH_TEST);

 

    // 深度测试的类型

    glDepthFunc(GL_LEQUAL);

 

    // 进行透视修正

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

   

    // 翡翠、祖母绿

    GLfloat mat_ambient[] = { 0.021500, 0.174500, 0.021500, 0.550000 };

    GLfloat mat_diffuse[] = { 0.075680, 0.614240, 0.075680, 0.550000 };

    GLfloat mat_specular[] = {0.633000, 0.727811, 0.633000, 0.550000};

    GLfloat mat_shininess[] = {76.800003 };

    glColor3f(1.0f, 1.0f, 1.0f);

   

    // 材质属性 

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);

    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);

    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);

    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);

 

    // 启动光照,使用缺省的光照参数 

    glEnable(GL_LIGHTING);

    glEnable(GL_LIGHT0);

 

    // 自动计算法向量

    glEnable(GL_AUTO_NORMAL);

 

    // 创建一个新的NURBS 对象

    theNurb = gluNewNurbsRenderer();

 

    // 设置NURBS 对象的参数

    gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);

    gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);

 

    return TRUE;

}

 

glShutdown 中必须添加将NURBS 对象释放的代码,否则,即便应用程序关闭,对象占用的内存也可能会一直无法释放。

 

void glShutdown()

{

    ……

    if(theNurb)

        gluDeleteNurbsRenderer(theNurb);

}

 

// 定义NURBS 的控制点,共25

GLfloat CtlPoints[5][5][3]=

{

    {{-3.0, -3.0, -3.0}, {-3.0, -1.0, -3.0}, {-3.0, 0.0, -3.0},

{-3.0, 1.0, -3.0}, {-3.0, 3.0, -3.0}},

 

    {{-1.0, -3.0, -3.0}, {-1.0, -1.0, -9.0}, {-1.0 ,0.0, 9.0},

{-1.0, 1.0, -9.0}, {-1.0, 3.0, -3.0}},

 

    {{1.0, -3.0, -3.0}, {1.0, -1.0, 3.0}, {1.0, 0.0, 3.0,},

{1.0, 1.0, 3.0}, {1.0, 3.0, -3.0}},

 

    {{3.0, -3.0, -3.0}, {3.0, -1.0, -3.0},{3.0, 0.0, -3.0},

  {3.0, 1.0, -3.0},{3.0, 3.0, -3.0}},

 

    {{5.0, -3.0, -3.0}, {5.0, -1.0, -9.0},{5.0, 0.0, 9.0},

{5.0, 1.0, -9.0},{5.0, 3.0, -3.0}}

};

 

 

GLfloat knots[10] = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0};

 

void glMain()

{

   

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();   // 加载单位矩阵

    glTranslatef(0.0f, -1.0f, -10.0f);

    glRotatef(90, 0.0f, 0.0f, 1.0f);

 

    // 根据按键确定切换显示模式     

    if(bModePressed)

    {

        bModePressed = FALSE;

        gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, DisplayMode[Mode]);

    }

   

    // 开始定义NURBS 曲面   

    gluBeginSurface(theNurb);

    gluNurbsSurface(theNurb,

        10,

        knots,

        10,

        knots,

        15,

        3,

        &CtlPoints[0][0][0],

        5, 5,

        GL_MAP2_VERTEX_3);

    gluEndSurface(theNurb);     // 结束曲面定义并显示

   

    SwapBuffers(g_hDC);// 交换前后缓冲区

 

程序运行后,可以看到一个脸部模型的大概轮廓已经显示出来。当然,真正的实现一个完整的面具模型还需要更多的控制点。按空格键后还可以看到网格状的曲面和仅有外边沿轮廓的曲面,仅有外边沿轮廓的曲面基本上已经看不出是一个曲面了,更象一个平面多边形。效果如图10-11 所示。


http://chatgpt.dhexx.cn/article/XeuLxh2U.shtml

相关文章

【Matlab-NURBS工具箱简要教程及实例 】

Matlab-NURBS工具箱使用教程 添加NURBS工具箱 在附加功能里添加NURBS工具箱 安装完成后可以在’函数’处查看API,也打开文件夹查看。 强烈推荐同步安装gnurbs工具,它完全代替nrbplot展示曲面,且允许用户进行节点拖拽等操作。 NURBS 结…

Nurbs曲线详解

NURBS(Non Uniform Rational B-spline)曲线通常称为非均匀有理B样条曲线,其数学定义如下: 基函数由递推公式定义: 非均匀:指节点向量的值与间距可以为任意值。这样我们可以在不同区间上得到不同的混合…

NURBS曲面结构及生成原理、修改方法

NURBS全称是Non-Uniform Rational B-Splines中文叫做非均匀有理B样条曲线,Rhinoceros中的模型曲线便是通过NRUBS曲线进行描述,曲面则是通过U和V两个方向的曲线集合来得到,如图: Rhino如何生产曲面原理 由上图我们发现就像织布一样…

MySQL数据库增量备份及恢复方案

MySQL数据库增量备份及恢复方案 u 前言 操作系统崩溃、电源故障、文件系统崩溃和硬件故障等异常状况都可能导致我们正在使用的数据库出现故障而产生数据库中数据不一致的情况。为了保证数据库使用安全,必须定期备份数据库;数据库备份可以分为&#xff1…

差异增量备份和累积增量备份区别(有图)

所谓增量备份,顾名思义即是每次备份仅操作那些发生了"变化"的数据块。RMAN中增量备份有两种:Differential 方式和Cumulative方式。 1、差异增量备份Differential 说起Differential,相当有意思,大家可以这样理解。有一…

数据库的备份与恢复(完全备份,增量备份)

目录 1. 数据库备份的分类1.1 从物理与逻辑的角度,备份可分为1.2 从数据库的备份策略角度,备份可分为 2. 常见的备份方法3. MySQL完全备份与分类3.1 完全备份概述3.2 备份方式3.2.1 物理冷备份及恢复3.2.2 使用专用备份工具 mysqldump3.2.2.1 备份库3.2.…

图解完全备份,增量备份,差异备份

因为网上说的全部都是copy的,所以自己去理解了一下然后整理了一下。 完全备份 完成备份我相信大家都理解,就是一下子备份所有的内容。 增量备份 如上图所示,比如一家公司,周一这家公司进行完全备份,然后周二备份周一…

MySQL 增量备份与恢复

目录 引言一、MySQL 增量备份1. 增量备份特点2. 示例 二、MySQL 增量恢复1. 增量恢复的场景2. 丢失完全备份之后更改的数据的恢复3. 完全备份之后丢失所有数据4. 基于时间点与位置的恢复4.1 基于时间点的恢复4.2 基于位置的恢复 5. 指定企业备份策略的思路 总结 引言 完全备份…

增量备份恢复

** 增量备份恢复案例 **1、配置mysql,设置日志文件 [rootlocalhost bak]# vim /etc/my.cnf 添加: log-binmysql-bin2、重启mysqld服务 systemctl restart mysqld查看日志文件: mysqlbinlog /usr/local/mysql/data/mysql-bin.0000013、创…

mysql实现增量备份

有点要注意 如果你误删了表 想通过这个恢复 必须恢复日志里面有创建表的日志 不然的话是无法回复的 就是必须是从你开始创建表的时候就已经记录日志了 恢复到哪个位置 就按照哪个位置来计算 mysql 5.0不支持增量备份 增量备份定义 mysql数据库会以二进制形式 自动把用户对my…

什么是全量备份,增量备份,差异备份?

背景 今天我司服务器工程大牛看我在备份数据,冷不丁提到了差异备份;但是才疏学浅的我却不知何为差异备份,故而以此为引,开始了对全量备份,增量备份,差异备份这三者的研习;经过一番寻觅,最终找到了他们.呵呵 希望大家有所受益! 问题 1. 什么是全量备份? 2. 什么是增量…

MySQL完全备份和增量备份

MySQL日治管理、数据库备份与恢复 备份的主要目的是灾难恢复,备份还可以测试应用、回滚数据修改、查询历史数据、审计等。而备份、恢复中,日志起到了很重要的作用 一、日志 MySQL的日志默认保存位置为 /usr/local/mysql/data 1.日志类型与作用 ①re…

MySQL 数据库备份(增量备份与恢复)

目录 一、MySQL 增量备份 1.增量备份的概念 1.1 为什么使用增量备份 1.2 增量备份的特点 2.增量备份示例 二、MySQL 增量恢复 1.增量恢复的场景 2.丢失完全备份之后更改的数据的恢复步骤 3.完全备份之后丢失所有数据的恢复步骤 4. 基于时间点与位置的恢复 4.1 基于时间…

mysql数据的备份与恢复

mysql数据的备份与恢复 日志的类型与作用:开启日志方式查看日志是否开启 数据备份的重要性:备份类型:如何选择逻辑备份策略或频率?常见的备份方法:MysQL完全备份优缺点:数据库完全备份分类: 实验…

完全备份 、差异备份、增量备份的区别和特点

数据备份的方式有完全备份、差异备份以及增量备份,那么这三种备份方式有什么区别,在具体应用中又该如何选择呢?本文就这些问题作以介绍。 一、备份方式简介 1、完全备份(Full Backup) 备份全部选中的文件夹&#xf…

MySQL 数据库备份(二)(增量备份与恢复)

文章目录 一、MySQL 增量备份1.增量备份的概念1.1 为什么使用增量备份1.2 增量备份的特点 2.增量备份示例 二、MySQL 增量恢复1.增量恢复的场景2.丢失完全备份之后更改的数据的恢复步骤3.完全备份之后丢失所有数据的恢复步骤4. 基于时间点与位置的恢复4.1 基于时间点的恢复4.1 …

增量备份

增量备份,是指在完整备份的基础上,每次只是备份自上次备份以来被修改过的数据块。增量备份策略不能用于映像备份,因为映像备份总是对于所有的数据文件。增量备份可以是数据库、数据文件和表空间三个级别。 一、增量备份的种类 第一、累积增…

PC端微信打不开小程序解决

PC端微信点击小程序之后没有啥反应,可以使用下面的方法解决:右键桌面的微信快捷方式,属性-兼容性,勾选上以兼容模式运行这个程序即可

微信外部链接无法使用浏览器打开 微信链接打不开的解决方案

域名在微信中打不开,有诸多问题 1、硬件原因,比如手机网络、手机缓存的手机硬件设备等 这里就不讨论硬件方便的问题 2、其他原因 目前的APP基本都支持二维码扫描下载,二维码下载也成为了大家用起来很顺手的一种方式。由于微信的用户基本占据…

微信中已停止访问该网页、据用户投诉及腾讯手机管家云网址检测、该网页包含不安全内容。为维护绿色上网环境,已停止访问的解决方案

不管是网站的首页,还是产品的页面地址,以及在线支付的地址,都有可能会被微信提示:已停止访问该网页,据用户投诉及腾讯网址安全中心检测,该网页包含违法或违规内容。为维护绿色上网环境,已停止访问。有的页面…