opengl动态贝塞尔曲线有差距 - glEvalCoord1f();

时间:2013-07-10 19:40:53

标签: c++ opengl glut freeglut

我喜欢有一个程序,您可以选择十个点,然后计算这些点的贝塞尔曲线。它看起来非常完美,但显示的曲线有一些差距。我用了GL_LINE_STRIP这些点怎么可能没有连接?

我发现,u中的glEvalCoord1f(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; } 中的控制点和窗口属性?

Beziere gaps Line width 1

[编辑]添加较粗线条的屏幕: Beziere gaps Line width 3

{{1}}

1 个答案:

答案 0 :(得分:2)

尝试将控制点Z coords归零:

#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;
}