2013-07-10 24 views
2

我喜欢有一个程序,你可以选择十个点,然后计算出一个贝塞尔曲线。它似乎工作非常完美,但显示的曲线有一些差距。我使用GL_LINE_STRIP这些点如何不可能连接?opengl动态贝塞尔曲线有间隙 - glEvalCoord1f();

我想,glEvalCoord1f(u);中的一个非常小的u会使间隙变小。 u如何取决于glEvalCoord1f(u);中的控制点和窗口属性?

Beziere gaps Line width 1

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

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

屏幕提供,这样可以很清楚的我改变了“float max = pow(MAXP,4)* 2;”到“float max = pow(MAXP,2)* 2;” – abimelex

+0

你能增加蓝线的大小吗? –

+0

我可以,但它不能解决问题。或者你需要它作为屏幕? – abimelex

回答

2

尝试归零的控制点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; 
} 
+0

是的,就是这样。感谢提示。 Z值总是2,这正是限幅值。我只是从Z中减去0.1f。 – abimelex