計算機圖形學-Bezier樣條曲面生成例項
阿新 • • 發佈:2019-01-31
Bezier樣條曲面
要求:
1. 畫一條Bezier樣條曲面,包含4*4個控制點
2. 用滑鼠調整控制點的位置,觀察曲面變化
使用工具:
1. Visual Studio C++控制檯
2. OpenGl
效果圖:
程式碼:
#include <GL/glut.h>
#include<math.h>
int xIndex, yIndex;//用於檢視滑鼠最近的控制點
bool onwork = false;
GLfloat pts[4][4][3] = {
{ { -5, 0, 8 }, { -2, 2, 0 }, { 2, 2, 0 }, { 5 , 0, 8 } },
{ {-5, 3, 2 }, { -2, 3, 0 }, { 2, 3, 0 }, { 5, 3, 2 } },
{ { -5, 6, 8 }, { -2, 6, 3 }, { 2, 6, 3 }, { 5, 6, 8 } },
{ { -5, 9, 0 }, { -2, 7, 0 }, { 2, 7, 0 }, { 5, 9, 0 } }
};
void init()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glOrtho(-10.0, 10.0,-10.0, 10.0, -10.0, 10.0);
glMap2f(GL_MAP2_VERTEX_3, 0 , 1, 3, 4, 0, 1, 12, 4, &pts[0][0][0]);
glEnable(GL_MAP2_VERTEX_3);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0, 1.0, 1.0, 1.0);
glColor3f(1.0, 0.0, 0.0);
int i, j;
for (j = 0; j <= 20; j++){
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 20; i++){
glEvalCoord2f((GLfloat)i / 20.0, (GLfloat)j / 20.0);
}
glEnd();
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 20; i++){
glEvalCoord2f((GLfloat)j / 20, (GLfloat)i / 20.0);
}
glEnd();
}
glColor3f(0.0, 0.0, 1.0);
glPointSize(2.5f);
glBegin(GL_POINTS);
for (i = 0; i < 4; i++){
for (j = 0; j < 4; j++){
glVertex2fv(pts[i][j]);
}
}
glEnd();
glFlush();
}
void display()
{
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &pts[0][0][0]);
glEnable(GL_MAP2_VERTEX_3);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw();
}
//計算滑鼠點選處與控制點之間的距離
double distance(int x, int y, float x2, float y2)
{
double dis = sqrt(pow(x - x2, 2) + pow(y - y2, 2));
return dis;
}
//將螢幕座標轉換為世界座標
void change(int *result)
{
int x = result[0], y = result[1];
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winx, winy, winz;
GLdouble posX, posY, posZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winx = (float)x;
winy = (float)viewport[3] - (float)y;
glReadPixels(x, int(winy), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winz);
gluUnProject(winx, winy,winz, modelview, projection, viewport, &posX, &posY, &posZ);
result[0] = posX;
result[1] = posY;
}
void click(int button, int state, int winx, int winy)
{
int result[] = { winx, winy };
change(result);
int x = result[0], y = result[1];
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
double dis = distance(x, y, pts[0][0][0], pts[0][0][1]);
double disTemp = dis;
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
dis = distance(x, y, pts[i][j][0], pts[i][j][1]);
if (dis <= disTemp){
xIndex = i;
yIndex = j;
disTemp = dis;
onwork = true;
}
}
}
}
}
void motion(int winx, int winy)
{
int result[] = { winx, winy };
change(result);
int x = result[0], y = result[1];
if (onwork){
pts[xIndex][yIndex][0] = x;
pts[xIndex][yIndex][1] = y;
draw();
}
}
void main(int argc, char * argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("Bezier");
init();
glutDisplayFunc(display);
glutMouseFunc(click);
glutMotionFunc(motion);
glutMainLoop();
}