OpenGL实现贝塞尔曲线或曲面

本文实例为大家分享了OpenGL实现贝塞尔曲线或曲面的具体代码,供大家参考,具体内容如下

理论基础

贝塞尔曲线和曲面:OpenGL只能直接绘制基本图元,对于曲线和曲面我们一般采用一系列线段或多边形来模拟的,这样当线段或多边形增多时必定很耗性能。其实对于这种曲线和曲面,我们可以使用一些控制点,通过求值器程序先计算出坐标等信息,然后直接用这些数据绘制,这样不仅节省内存,还提高了模拟曲线或曲面的精度(本质还是通过线段或多边形绘制的,只是求值器提前算出了曲线或曲面的顶点信息)。

求值器使用一般步骤:1.启用求值器 2.定义求值器 3.执行求值器。

注释:OpenGl3.1后,本节内容都已经废弃了,这些顶点着色器都可以实现了。

代码示例

1、曲线

#include "GLTools.h"

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

//控制点
GLfloat ctrlpoints[4][3] = {
 { -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0},
 {2.0, -4.0, 0.0}, {4.0, 4.0, 0.0}};

void init(void)
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glShadeModel(GL_FLAT);
 //定义一维求值器
 glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
 //启动求职器
 glEnable(GL_MAP1_VERTEX_3);
}

void display(void)
{
 int i;

 glClear(GL_COLOR_BUFFER_BIT);
 glColor3f(1.0, 1.0, 1.0);
 glBegin(GL_LINE_STRIP);
 for (i = 0; i <= 30; i++)
  glEvalCoord1f((GLfloat) i/30.0);//执行求值器,每执行一次产生一个坐标
 glEnd();

 //绘制4个控制点
 glPointSize(5.0);
 glColor3f(1.0, 1.0, 0.0);
 glBegin(GL_POINTS);
 for (i = 0; i < 4; i++)
  glVertex3fv(&ctrlpoints[i][0]);
 glEnd();
 glFlush();
}

void reshape(int w, int h)
{
 glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 if (w <= h)
  glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
    5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
 else
  glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
    5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
}

void keyboard(unsigned char key, int x, int y)
{
 switch (key) {
  case 27:
   exit(0);
   break;
 }
}

int main(int argc, char** argv)
{
 glutInit(&argc, argv);
 glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
 glutInitWindowSize (500, 500);
 glutInitWindowPosition (100, 100);
 glutCreateWindow (argv[0]);
 init ();
 glutDisplayFunc(display);
 glutReshapeFunc(reshape);
 glutKeyboardFunc (keyboard);
 glutMainLoop();
 return 0;
}

2、曲面

#include "GLTools.h"

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

GLfloat ctrlpoints[4][4][3] = {
 {{ -1.5, -1.5, 4.0}, { -0.5, -1.5, 2.0},
  {0.5, -1.5, -1.0}, {1.5, -1.5, 2.0}},
 {{ -1.5, -0.5, 1.0}, { -0.5, -0.5, 3.0},
  {0.5, -0.5, 0.0}, {1.5, -0.5, -1.0}},
 {{ -1.5, 0.5, 4.0}, { -0.5, 0.5, 0.0},
  {0.5, 0.5, 3.0}, {1.5, 0.5, 4.0}},
 {{ -1.5, 1.5, -2.0}, { -0.5, 1.5, -2.0},
  {0.5, 1.5, 0.0}, {1.5, 1.5, -1.0}}
};

GLfloat texpts[2][2][2] = {{{0.0, 0.0}, {0.0, 1.0}},
 {{1.0, 0.0}, {1.0, 1.0}}};

void display(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glColor3f(1.0, 1.0, 1.0);
 glEvalMesh2(GL_FILL, 0, 20, 0, 20);//glMapGrid2f()均匀产生坐标值,这里执行绘制
 glFlush();
}

#define imageWidth 64
#define imageHeight 64
GLubyte image[3*imageWidth*imageHeight];
//纹理数据
void makeImage(void)
{
 int i, j;
 float ti, tj;

 for (i = 0; i < imageWidth; i++) {
  ti = 2.0*3.14159265*i/imageWidth;
  for (j = 0; j < imageHeight; j++) {
   tj = 2.0*3.14159265*j/imageHeight;

   image[3*(imageHeight*i+j)] = (GLubyte) 127*(1.0+sin(ti));
   image[3*(imageHeight*i+j)+1] = (GLubyte) 127*(1.0+cos(2*tj));
   image[3*(imageHeight*i+j)+2] = (GLubyte) 127*(1.0+cos(ti+tj));
  }
 }
}

void init(void)
{
 //定义了两个求值器程序
 glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
   0, 1, 12, 4, &ctrlpoints[0][0][0]);
 glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2,
   0, 1, 4, 2, &texpts[0][0][0]);
 glEnable(GL_MAP2_TEXTURE_COORD_2);
 glEnable(GL_MAP2_VERTEX_3);
 glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);//均匀产生坐标

 //纹理属性设置
 makeImage();
 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageWidth, imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
 glEnable(GL_TEXTURE_2D);
 glEnable(GL_DEPTH_TEST);
 glShadeModel (GL_FLAT);
}

void reshape(int w, int h)
{
 glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 if (w <= h)
  glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w,
    4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
 else
  glOrtho(-4.0*(GLfloat)w/(GLfloat)h,
    4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glRotatef(85.0, 1.0, 1.0, 1.0);
}

void keyboard(unsigned char key, int x, int y)
{
 switch (key) {
  case 27:
   exit(0);
   break;
 }
}

int main(int argc, char** argv)
{
 glutInit(&argc, argv);
 glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
 glutInitWindowSize (500, 500);
 glutInitWindowPosition (100, 100);
 glutCreateWindow (argv[0]);
 init ();
 glutDisplayFunc(display);
 glutReshapeFunc(reshape);
 glutKeyboardFunc(keyboard);
 glutMainLoop();
 return 0;

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • OpenGL绘制Bezier曲线的方法

    本文实例为大家分享了OpenGL绘制Bezier曲线的具体代码,供大家参考,具体内容如下 项目要求: – 使用鼠标在屏幕中任意设置控制点,并生成曲线 – 使用鼠标和键盘的交互操作实现对曲线的修改. 项目总体介绍 本项目利用Bezier曲线生成算法生成可由用户自定义的曲线.可实现核心功能如下: 1.用户用鼠标左击屏幕任意处产生记录点. 2.鼠标右击屏幕任意处由先前的任意个数记录点和其先后关系生成Bezier曲线. 另有辅助输入功能: 1.按键盘'C'键可清除所有记录点. 2.按键盘'R'键可清除上

  • OpenGL实现Bezier曲线的方法示例

    Bezier曲线的形状是通过一组多边折线(特征多边形)的各顶点唯一地定义出来的.在这组顶点中: (1)只有第一个顶点和最后一个顶点在曲线上: (2)其余的顶点则用于定义曲线的导数.阶次和形状: (3)第一条边和最后一条边则表示了曲线在两端点处的切线方向. // BezierCurve.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h"</div></div></li><li><div class=

  • 使用OpenGL绘制Bezier曲线

    本文实例为大家分享了OpenGL绘制Bezier曲线的具体代码,供大家参考,具体内容如下 最近在看Francis S Hill ,Jr 和 Stephen M Kelley合著的<计算机图形学>(OpenGL版)(第三版)书中有绘制三个控制点的Bezier曲线的代码.自己重新敲了一遍代码.发现了其中的一点小错误,修正过来了.并做了一点小小的改动. 源码见下 #include <windows.h> #include <math.h> #include <gl/GL

  • OpenGL画bezier曲线

    Bezier Curve算法是根据参数曲线方程来得到光滑曲线的一种算法,曲线方程的参数由控制点决定. 其本质是由调和函数根据控制点插值而成,其参数方程如下: 其中Pi(i=0,1,-,n)为控制点的向量, Bi,n(t)为伯恩斯坦Bernstein基函数,其多项式表示为: 线性Bezier Curve由两个控制点决定: 二次Bezier Curve由三个控制点决定: 三次Bezier Curve由四个控制点决定: 如下图,t = AE:AB = BF:BC = CG:CD = EH:EF = F

  • OpenGL绘制三次Bezier曲线

    本文实例为大家分享了OpenGL绘制三次Bezier曲线的具体代码,供大家参考,具体内容如下 计算公式: 运行结果: 代码如下: #include<gl/glut.h> #include<math.h> #include<windows.h> #include<vector> #include<algorithm> using namespace std; struct Point { int x, y; Point(){}; Point(int

  • OpenGL绘制贝塞尔曲线

    本文实例为大家分享了OpenGL绘制贝塞尔曲线的具体代码,供大家参考,具体内容如下 最终效果图: 通过3个点形成一条贝塞尔曲线 1. 鼠标问题 在使用鼠标获取坐标的时候,要知道鼠标获取的坐标和屏幕坐标是不同的; openGL使用右手坐标 从左到右,x递增 从下到上,y递增 从远到近,z递增 而鼠标是从左到右增x,同时从上到下也是增y 所以在求 y 的时候,用(屏幕大小-y)来获取 2. 绘制 setpoint 用来绘制点 setline 用来绘制线 setBezier 用来绘制贝塞尔曲线 其中公

  • OpenGL实现贝塞尔曲线或曲面

    本文实例为大家分享了OpenGL实现贝塞尔曲线或曲面的具体代码,供大家参考,具体内容如下 理论基础 贝塞尔曲线和曲面:OpenGL只能直接绘制基本图元,对于曲线和曲面我们一般采用一系列线段或多边形来模拟的,这样当线段或多边形增多时必定很耗性能.其实对于这种曲线和曲面,我们可以使用一些控制点,通过求值器程序先计算出坐标等信息,然后直接用这些数据绘制,这样不仅节省内存,还提高了模拟曲线或曲面的精度(本质还是通过线段或多边形绘制的,只是求值器提前算出了曲线或曲面的顶点信息). 求值器使用一般步骤:1.

  • iOS贝塞尔曲线画哆啦A梦的代码实例

    看到这张图,是不是觉得挺萌的,那是如何实现的呢?在iOS中有一个类叫UIBezierPath(贝塞尔曲线),这两天研究了一下UIBezierPath和CAShapeLayer,根据别人分享的教程,画了这个萌萌的哆啦A梦. UIBezierPath: UIBezierPath是在 UIKit 中的一个类,继承于NSObject,可以创建基于矢量的路径.此类是Core Graphics框架关于path的一个OC封装.使用此类可以定义常见的圆形.多边形等形状 .我们使用直线.弧(arc)来创建复杂的曲

  • IOS 贝塞尔曲线(UIBezierPath)属性、方法整理

    IOS 贝塞尔曲线详解         开发IOS的朋友都知道IOS 贝塞尔曲线的重要性,由于经常会用到这样的东西,索性抽时间就把相应所有的属性,方法做一个总结. UIBezierPath主要用来绘制矢量图形,它是基于Core Graphics对CGPathRef数据类型和path绘图属性的一个封装,所以是需要图形上下文的(CGContextRef),所以一般UIBezierPath在drawRect中使用. UIBezierPath的属性介绍: 1.CGPath:将UIBezierPath类转

  • 快速上手IOS UIBezierPath(贝塞尔曲线)

    UIBezierPath主要用来绘制矢量图形,它是基于Core Graphics对CGPathRef数据类型和path绘图属性的一个封装,所以是需要图形上下文的(CGContextRef),所以一般UIBezierPath在drawRect中使用. 使用方法 UIBezierPath 是对 CGPathRef 的封装.创建矢量图形时,拆解成一或多条线段,拼接起来,每条线段的终点都是下一条线段的起点. 具体地: 1.创建一个 UIBezierPath 对象 2.用 moveToPoint: 设置初

  • ios 贝塞尔曲线切割圆角的方法

    ios 系统框架已经给我们提供了相应的切割圆角的方法, 但是如果在一个见面有很多控件切割的话会出现卡顿和个别不切得现在 /* 创建一个Button */ UIButton * button = [UIButton buttonWithType:(UIButtonTypeSystem)]; [button setFrame:CGRectMake(100, 100, 100, 100)]; [self addSubview:button]; /* 正厂的圆角需求处理方法 */ button.laye

  • Android把商品添加到购物车的动画效果(贝塞尔曲线)

    当我们写商城类的项目的时候,一般都会有加入购物车的功能,加入购物车的时候会有一些抛物线动画,具体代码如下: 实现效果如图: 思路: 确定动画的起终点 在起终点之间使用二次贝塞尔曲线填充起终点之间的点的轨迹 设置属性动画,ValueAnimator插值器,获取中间点的坐标 将执行动画的控件的x.y坐标设为上面得到的中间点坐标 开启属性动画 当动画结束时的操作 难点: PathMeasure的使用 - getLength() - boolean getPosTan(float distance, f

  • Android贝塞尔曲线初步学习第二课 仿QQ未读消息气泡拖拽黏连效果

    上一节初步了解了Android端的贝塞尔曲线,这一节就举个栗子练习一下,仿QQ未读消息气泡,是最经典的练习贝塞尔曲线的东东,效果如下 附上github源码地址:https://github.com/MonkeyMushroom/DragBubbleView 欢迎star~ 大体思路就是画两个圆,一个黏连小球固定在一个点上,一个气泡小球跟随手指的滑动改变坐标.随着两个圆间距越来越大,黏连小球半径越来越小.当间距小于一定值,松开手指气泡小球会恢复原来位置:当间距超过一定值之后,黏连小球消失,气泡小球

随机推荐