opengl 动态贝塞尔曲线有间隙 - glEvalCoord1f();
Posted
技术标签:
【中文标题】opengl 动态贝塞尔曲线有间隙 - glEvalCoord1f();【英文标题】:opengl dynamic bezier curve has gaps - glEvalCoord1f(); 【发布时间】:2013-07-10 19:40:53 【问题描述】:我喜欢有一个程序,您可以在其中选择十个点,然后为这些点计算贝塞尔曲线。它似乎工作得非常完美,但显示的曲线有一些差距。我用GL_LINE_STRIP
怎么可能点不通?
我发现,glEvalCoord1f(u);
中的一个非常小的u
会使差距更小。
u
如何取决于 glEvalCoord1f(u);
中的控制点和窗口属性?
[编辑] 添加了粗线条的屏幕:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <math.h>
#include <time.h>
#include <GL/glut.h> //added GL prefix for Ubuntu compatibility
#define MAXP 10
GLint nNumPoints = 0;
GLfloat ctrlpoints[10][3];
GLdouble mouseOgl[3] = 0.0,0.0,0.0;
GLint mouseX, mouseY;
bool mousePressed = false;
void GetOGLPos(int x, int y);
void init(void)
glClearColor(1.0, 1.0, 1.0, 0.0);
glShadeModel(GL_FLAT);
// Enable the evaluator
glEnable(GL_MAP1_VERTEX_3);
glEnable(GL_DEPTH);
void display(void)
int i;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 0.0, 1.0);
if(mousePressed && nNumPoints < MAXP)
GetOGLPos(mouseX, mouseY);
std::cout
<< mouseOgl[0] << " # "
<< mouseOgl[1] << " # "
<< mouseOgl[2] << " # "
<< std::endl;
nNumPoints++;
ctrlpoints[nNumPoints-1][0] = mouseOgl[0];
ctrlpoints[nNumPoints-1][3] = mouseOgl[1];
ctrlpoints[nNumPoints-1][2] = mouseOgl[2];
//Curves
if( nNumPoints == MAXP )
glMap1f(GL_MAP1_VERTEX_3, // Type of data generated
0.0f, // Lower u range
1.0f, // Upper u range
3, // Distance between points in the data 3: ...Z-X-Y-Z...
nNumPoints, // number of control points
&ctrlpoints[0][0]); // start point
glBegin(GL_LINE_STRIP);
float max = pow(MAXP,4)*2; //accuracy of pint calulation?
for (i = 0; i <= max; i++)
glEvalCoord1f((GLfloat) (i/max)); //high value to avoid gaps?!?
glEnd();
//Controllpoints:
glPointSize(5.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < nNumPoints; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
//Lines
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
for (i = 0; i < nNumPoints; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
if( nNumPoints == MAXP )nNumPoints = 0;
glFlush();
void reshape(int w, int h)
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//keep aspect ratio:
if (w <= h)
glOrtho(-2.0, 2.0, -2.0*(GLfloat)h/(GLfloat)w,
2.0*(GLfloat)h/(GLfloat)w, -2.0, 2.0);
else
glOrtho(-2.0*(GLfloat)w/(GLfloat)h,
2.0*(GLfloat)w/(GLfloat)h, -2.0, 2.0, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//handle click events of the mouse
void myMouse(int button, int state, int x, int y)
//mouse coords to gl coords
mouseX = x;
mouseY = y;
switch (button)
case GLUT_LEFT_BUTTON:
if(state == GLUT_UP) //on release left mouse button
std::cout << x << " * "<< y << std::endl;
mousePressed = true;
glutPostRedisplay(); //redisplay and calculate gl coords
else
mousePressed = false;
break;
// detailed information:
// http://nehe.gamedev.net/article/using_gluunproject/16013/
void GetOGLPos(int x, int y)
//init vars:
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
//get gl specs
glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); //get Modelmatrix
glGetDoublev( GL_PROJECTION_MATRIX, projection ); //get projection matrix
glGetIntegerv( GL_VIEWPORT, viewport ); //get viewport values
//calculate the gl mouseposition
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);
mouseOgl[0] = posX;
mouseOgl[1] = posY;
mouseOgl[2] = posZ;
int main(int argc, char** argv)
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (600, 600);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(myMouse);
glutMainLoop();
return 0;
【问题讨论】:
提供了屏幕,为了使屏幕更清晰,我更改了“float max = pow(MAXP,4)*2;”到“浮动最大值 = pow(MAXP,2)*2;” 可以增加蓝线的大小吗? 可以,但不能解决问题。还是你需要它作为屏幕? 我添加了第二个屏幕,显示线条较粗的问题。还是一样…… 【参考方案1】:尝试将控制点 Z 坐标归零:
#include <GL/glut.h>
#include <cmath>
const unsigned int MAXP = 10;
GLint nNumPoints = 0;
GLfloat ctrlpoints[10][3];
GLdouble mouseOgl[3] = 0.0,0.0,0.0;
GLint mouseX, mouseY;
bool mousePressed = false;
void GetOGLPos(int x, int y);
void display(void)
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
int w = glutGet( GLUT_WINDOW_WIDTH );
int h = glutGet( GLUT_WINDOW_HEIGHT );
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double ar = w / (double)h;
glOrtho(-2.0*ar, 2.0*ar, -2.0, 2.0, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(mousePressed && nNumPoints < MAXP)
GetOGLPos(mouseX, mouseY);
nNumPoints++;
ctrlpoints[nNumPoints-1][0] = mouseOgl[0];
ctrlpoints[nNumPoints-1][1] = mouseOgl[1];
// this is where the magic happens:
ctrlpoints[nNumPoints-1][2] = 0;
//Curves
glColor3f(0.0, 0.0, 1.0);
if( nNumPoints == MAXP )
glMap1f(GL_MAP1_VERTEX_3, // Type of data generated
0.0f, // Lower u range
1.0f, // Upper u range
3, // Distance between points in the data 3: ...Z-X-Y-Z...
nNumPoints, // number of control points
&ctrlpoints[0][0]); // start point
glBegin(GL_LINE_STRIP);
float max = pow(MAXP,4.0)*2; //accuracy of pint calulation?
for (int i = 0; i <= max; i++)
glEvalCoord1f((GLfloat) (i/max)); //high value to avoid gaps?!?
glEnd();
//Controllpoints:
glPointSize(5.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
for (int i = 0; i < nNumPoints; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
//Lines
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < nNumPoints; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
if( nNumPoints == MAXP )nNumPoints = 0;
glFlush();
//handle click events of the mouse
void myMouse(int button, int state, int x, int y)
//mouse coords to gl coords
mouseX = x;
mouseY = y;
switch (button)
case GLUT_LEFT_BUTTON:
if(state == GLUT_UP) //on release left mouse button
mousePressed = true;
glutPostRedisplay(); //redisplay and calculate gl coords
else
mousePressed = false;
break;
// detailed information:
// http://nehe.gamedev.net/article/using_gluunproject/16013/
void GetOGLPos(int x, int y)
//init vars:
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
//get gl specs
glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); //get Modelmatrix
glGetDoublev( GL_PROJECTION_MATRIX, projection ); //get projection matrix
glGetIntegerv( GL_VIEWPORT, viewport ); //get viewport values
//calculate the gl mouseposition
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);
mouseOgl[0] = posX;
mouseOgl[1] = posY;
mouseOgl[2] = posZ;
int main(int argc, char** argv)
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (600, 600);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
glShadeModel(GL_FLAT);
// Enable the evaluator
glEnable(GL_MAP1_VERTEX_3);
glEnable(GL_DEPTH);
glutDisplayFunc(display);
glutMouseFunc(myMouse);
glutMainLoop();
return 0;
【讨论】:
是的,就是这样。感谢您的提示。 Z 值始终为 2,这正是剪裁值。我现在从 Z 中减去了 0.1f。以上是关于opengl 动态贝塞尔曲线有间隙 - glEvalCoord1f();的主要内容,如果未能解决你的问题,请参考以下文章