OpenGL繪制貝塞爾曲線
本文實例為大家分享了OpenGL繪制貝塞爾曲線的具體代碼,供大家參考,具體內(nèi)容如下
最終效果圖:
通過3個點形成一條貝塞爾曲線

1. 鼠標問題
在使用鼠標獲取坐標的時候,要知道鼠標獲取的坐標和屏幕坐標是不同的;
openGL使用右手坐標
從左到右,x遞增
從下到上,y遞增
從遠到近,z遞增
而鼠標是從左到右增x,同時從上到下也是增y
所以在求 y 的時候,用(屏幕大小-y)來獲取
2. 繪制
setpoint 用來繪制點
setline 用來繪制線
setBezier 用來繪制貝塞爾曲線
其中公式的意義可以參考百科:

實際繪制的時候就是不斷的增加t,求出下一點的值然后將兩個鏈接起來,然后再將下一個點作為起點,再求出下下一個點
Api解釋在代碼中
#include "GL\glut.h"
#include <math.h>
#include <Windows.h>
//這是一個點的類,用于存儲其中點的坐標
class Point
{
public:
int x, y;
void setxy(int _x, int _y) {
x = _x;
y = _y;
}
};
//點的數(shù)量
static int POINTSNUM = 0;
//用于存儲點的集合,因為繪制的都是4個點的貝塞爾曲線,所以數(shù)組大小為4
static Point points[4];
//初始化函數(shù)
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0); //設定背景為黑色
glColor3f(0.0,0.0,0.0); //繪圖顏色為白色
glPointSize(2.0); //設定點的大小為2*2像素的
glMatrixMode(GL_PROJECTION); // 設定合適的矩陣
glLoadIdentity(); // 是一個無參的無值函數(shù),其功能是用一個4×4的單位矩陣來替換當前矩陣,實際上就是對當前矩陣進行初始化。也就是說,無論以前進行了多少次矩陣變換,在該命令執(zhí)行后,當前矩陣均恢復成一個單位矩陣,即相當于沒有進行任何矩陣變換狀態(tài)
gluOrtho2D(0.0,600.0,0.0,480.0); //平行投影,四個參數(shù)分別是x,y范圍
}
//繪制點
void setPoint(Point p) {
glBegin(GL_POINTS);
glVertex2f(p.x, p.y);
glEnd();
glFlush();
}
// 繪制直線
void setline(Point p1, Point p2) {
glBegin(GL_LINES);
glVertex2f(p1.x,p1.y);
glVertex2f(p2.x, p2.y);
glEnd();
glFlush();
}
// 繪制貝塞爾曲線
Point setBezier(Point p1, Point p2, Point p3, Point p4,double t) {
Point p;
double a1 = pow((1 - t), 3);
double a2 = pow((1 - t), 2) * 3 * t;
double a3 = 3 * t*t*(1 - t);
double a4 = t*t*t;
p.x = a1*p1.x + a2*p2.x + a3*p3.x + a4*p4.x;
p.y = a1*p1.y + a2*p2.y + a3*p3.y + a4*p4.y;
return p;
}
//display函數(shù)
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
// 鼠標事件
void mymouseFunction(int button, int state, int x, int y) {
if (state == GLUT_DOWN) // 如果鼠標按下,不區(qū)分左右鍵的
{
points[POINTSNUM].setxy(x,480- y); // 這里求鼠標點的坐標的時候
// 設置點的顏色,繪制點
glColor3f(1.0,0.0,0.0);
setPoint(points[POINTSNUM]);
// 設置線的顏色,繪制線
glColor3f(1.0,0.0,0.0);
if(POINTSNUM > 0) setline(points[POINTSNUM-1],points[POINTSNUM]);
//如果達到了4個繪制貝塞爾曲線,并在之后給計數(shù)器清零
if (POINTSNUM == 3) {
//繪制貝塞爾曲線
glColor3f(0.0, 0.0, 1.0); // 設定貝塞爾曲線的顏色
Point p_current = points[0]; //設為起點
for (double t = 0.0; t <= 1.0; t += 0.05)
{
Point P = setBezier(points[0], points[1], points[2], points[3], t);
setline(p_current, P);
p_current = P;
}
POINTSNUM = 0;
}
else {
POINTSNUM++;
}
}
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv); //固定格式
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //緩存模式
glutInitWindowSize(600, 480); //顯示框的大小
glutInitWindowPosition(100, 100); //確定顯示框左上角的位置
glutCreateWindow("第四次作業(yè)");
init(); // 初始化
glutMouseFunc(mymouseFunction); // 添加鼠標事件
glutDisplayFunc(display); // 執(zhí)行顯示
glutMainLoop(); //進人GLUT事件處理循環(huán)
return 0;
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
VSCODE調(diào)試RDKit內(nèi)核的方法步驟(C++)
本文主要介紹了VSCODE調(diào)試RDKit內(nèi)核的方法步驟,這個過程可以分為三個部分:安裝 RDKit 所需環(huán)境,安裝 VSCode 相應插件, 寫調(diào)試代碼編譯,感興趣的可以了解一下2021-08-08
C++流程控制中用于跳轉(zhuǎn)的return和goto語句學習教程
這篇文章主要介紹了C++流程控制中用于跳轉(zhuǎn)的return和goto語句學習教程,是C++入門學習中的基礎(chǔ)知識,需要的朋友可以參考下2016-01-01

