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();的主要内容,如果未能解决你的问题,请参考以下文章

使用 c++ opengl 的贝塞尔曲线

✠OpenGL-11-参数曲面

Bezier曲线原理—动态解释

从阅读仿真页看贝塞尔曲线

非常缓慢的软件向量,尤其是 CoreGraphics 与 OpenGL

收集资料OpenGL学习