2010-11-01 36 views
0

ce code dessine correctement les courbes bezier lorsque la fenêtre est utilisée sur sa taille d'origine (640 x 480) mais rend les points de contrôle incorrectement lors de sa redimensionnement.Comment puis-je obtenir ce programme pour dessiner la courbe bezier correctement après avoir été redimensionné?

sur la fonction de la souris il y a clic:

if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { 
    // Store where the user clicked, note Y is backwards. 
    abc[NUMPOINTS].setxy((float)x,(float)(SCREEN_HEIGHT - y)); 
    NUMPOINTS++; 

    // Draw the red dot. 
    drawDot(x, SCREEN_HEIGHT - y); 

Je ne comprends pas comment le système de coordonnées est en cours de traitement. Pourquoi utiliser la conversion SCREEN_HEIGHT sur 640x480 mais pas dans d'autres tailles de fenêtre? Pourquoi? Comment peut-il être rendu universel?

Sur mes propres applications, je travaillais sans glutOrtho2d et en utilisant simplement un calcul pour chaque X, Y mais j'ai lu que cette approche est meilleure. J'apprécierais une explication détaillée.

CODE MODIFIÉ:

/* bezier.cpp by [email protected] 
* 
* Create a bezier curve by defining the three points 
* with your mouse. 
* 
* http://www.metalshell.com/ 
* 
*/ 

#include <windows.h> 
#include <math.h> 
#include <gl/Gl.h> 
#include <gl/Glu.h> 
#include <gl/glut.h> 

// CREEN_WIDTH = 640, SCREEN_HEIGHT=480; 

int SCREEN_WIDTH=640; 

int SCREEN_HEIGHT = 480; 
// Keep track of times clicked, on 3 clicks draw. 
int NUMPOINTS = 0; 

// Point class to keep it a little cleaner. 
class Point { 
public: 
    float x, y; 
    void setxy(float x2, float y2) { x = x2; y = y2; } 
    const Point & operator=(const Point &rPoint) { 
     x = rPoint.x; 
     y = rPoint.y; 

     return *this; 
     } 

}; 

Point abc[3]; 

void myInit() { 
    glClearColor(0.0,0.0,0.0,0.0); 
    glColor3f(1.0,0.0,0.0); 
    glPointSize(4.0); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluOrtho2D(0.0,(float)SCREEN_WIDTH,0.0,(float)SCREEN_HEIGHT); 

} 

void drawDot(int x, int y) { 
    glBegin(GL_POINTS); 
    glVertex2i(x,y); 
    glEnd(); 
    glFlush(); 
} 

void drawLine(Point p1, Point p2) { 
    glBegin(GL_LINES); 
     glVertex2f(p1.x, p1.y); 
     glVertex2f(p2.x, p2.y); 
    glEnd(); 
    glFlush(); 
} 

// Calculate the next bezier point. 
Point drawBezier(Point A, Point B, Point C, double t) { 
    Point P; 

    P.x = pow((1 - t), 2) * A.x + 2 * t * (1 -t) * B.x + pow(t, 2) * C.x; 
    P.y = pow((1 - t), 2) * A.y + 2 * t * (1 -t) * B.y + pow(t, 2) * C.y; 

    return P; 
} 

void myMouse(int button, int state, int x, int y) { 
    // If left button was clicked 
    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { 
     // Store where the user clicked, note Y is backwards. 
     //abc[NUMPOINTS].setxy((float)x,(float)(y)); 
    abc[NUMPOINTS].setxy((float)x,(float)(SCREEN_HEIGHT - y)); 

    // abc[NUMPOINTS] es un arreglo de objetos Point, su contraparte en Casteljau es 


    NUMPOINTS++; 

    // Draw the red dot. 
    drawDot(x, SCREEN_HEIGHT - y); 
    //drawDot(x, SCREEN_HEIGHT); 

    // If 3 points are drawn do the curve. 
    if(NUMPOINTS == 3) { 
     glColor3f(1.0,1.0,1.0); 
     // Draw two legs of the triangle 
     drawLine(abc[0], abc[1]); 
     drawLine(abc[1], abc[2]); 
     Point POld = abc[0]; 
     /* Draw each segment of the curve. Make t increment in 
        smaller amounts for a more detailed curve. */ 
     for(double t = 0.0;t <= 1.0; t += 0.1) { 
      Point P = drawBezier(abc[0], abc[1], abc[2], t); 
      drawLine(POld, P); 
      POld = P; 
     } 
     glColor3f(1.0,0.0,0.0); 
     NUMPOINTS = 0; 
    } 
    } 
} 

void myDisplay() { 
    glClear(GL_COLOR_BUFFER_BIT); 
    glFlush(); 
} 

int main(int argc, char *argv[]) { 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); 
    glutInitWindowSize(SCREEN_WIDTH,SCREEN_HEIGHT); 
    glutInitWindowPosition(100,150); 
    glutCreateWindow("Bezier Curve"); 

    glutMouseFunc(myMouse); 
    glutDisplayFunc(myDisplay); 

    myInit(); 
    glutMainLoop(); 

    return 0; 
} 

CODE ORIGINAL:

/* bezier.cpp by [email protected] 
    * 
    * Create a bezier curve by defining the three points 
    * with your mouse. 
    * 
    * http://www.metalshell.com/ 
    * 
    */ 

    #include <windows.h> 
    #include <math.h> 
    #include <gl/Gl.h> 
    #include <gl/Glu.h> 
    #include <gl/glut.h> 

    int SCREEN_HEIGHT = 480; 
    // Keep track of times clicked, on 3 clicks draw. 
    int NUMPOINTS = 0; 

    // Point class to keep it a little cleaner. 
    class Point { 
    public: 
    float x, y; 
    void setxy(float x2, float y2) { x = x2; y = y2; } 
    const Point & operator=(const Point &rPoint) { 
     x = rPoint.x; 
     y = rPoint.y; 

     return *this; 
     } 

}; 

Point abc[3]; 

void myInit() { 
    glClearColor(0.0,0.0,0.0,0.0); 
    glColor3f(1.0,0.0,0.0); 
    glPointSize(4.0); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluOrtho2D(0.0,640.0,0.0,480.0); 

} 

void drawDot(int x, int y) { 
    glBegin(GL_POINTS); 
    glVertex2i(x,y); 
    glEnd(); 
    glFlush(); 
} 

void drawLine(Point p1, Point p2) { 
    glBegin(GL_LINES); 
     glVertex2f(p1.x, p1.y); 
     glVertex2f(p2.x, p2.y); 
    glEnd(); 
    glFlush(); 
} 

// Calculate the next bezier point. 
Point drawBezier(Point A, Point B, Point C, double t) { 
    Point P; 

    P.x = pow((1 - t), 2) * A.x + 2 * t * (1 -t) * B.x + pow(t, 2) * C.x; 
    P.y = pow((1 - t), 2) * A.y + 2 * t * (1 -t) * B.y + pow(t, 2) * C.y; 

    return P; 
} 

void myMouse(int button, int state, int x, int y) { 
    // If left button was clicked 
    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { 
     // Store where the user clicked, note Y is backwards. 
    abc[NUMPOINTS].setxy((float)x,(float)(SCREEN_HEIGHT - y)); 
    NUMPOINTS++; 

    // Draw the red dot. 
    drawDot(x, SCREEN_HEIGHT - y); 

    // If 3 points are drawn do the curve. 
    if(NUMPOINTS == 3) { 
     glColor3f(1.0,1.0,1.0); 
     // Draw two legs of the triangle 
     drawLine(abc[0], abc[1]); 
     drawLine(abc[1], abc[2]); 
     Point POld = abc[0]; 
     /* Draw each segment of the curve. Make t increment in 
        smaller amounts for a more detailed curve. */ 
     for(double t = 0.0;t <= 1.0; t += 0.1) { 
      Point P = drawBezier(abc[0], abc[1], abc[2], t); 
      drawLine(POld, P); 
      POld = P; 
     } 
     glColor3f(1.0,0.0,0.0); 
     NUMPOINTS = 0; 
    } 
    } 
} 

void myDisplay() { 
    glClear(GL_COLOR_BUFFER_BIT); 
    glFlush(); 
} 

int main(int argc, char *argv[]) { 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); 
    glutInitWindowSize(640,480); 
    glutInitWindowPosition(100,150); 
    glutCreateWindow("Bezier Curve"); 

    glutMouseFunc(myMouse); 
    glutDisplayFunc(myDisplay); 

    myInit(); 
    glutMainLoop(); 

    return 0; 
} 

Répondre

2

changement dans votre code EVERYWHERE qui utilise 640 ou 480 à utiliser SCREEN_WIDTH et SCREEN_HEIGHT.

ie.

gluOrtho2D(0.0,640.0,0.0,480.0); 

=>

gluOrtho2D(0.0,(float)SCREEN_WIDTH,0.0,(float)SCREEN_HEIGHT); 

&

glutInitWindowSize(640,480); 

=>

glutInitWindowSize(SCREEN_WDITH, SCREEN_HEIGHT); 

De cette façon, lorsque vous changez SCREEN_WIDTH ou screen_height vous n'êtes pas Dépendre uniquement moi valeurs définies ailleurs. Je soupçonne que votre problème est parce que vous ne modifiez l'appel gluOrtho2D ...

+0

Oh, je l'ai fait! En fait, j'avais changé depuis longtemps, mais j'ai annulé les changements car ils ne fonctionnaient pas. Lorsque la fenêtre est redimensionnée et que l'on essaie de dessiner des points en cliquant, ils apparaissent là où ils ne devraient pas. Je suspecte que le problème est avec cette conversion SCREEN_HEIGHT - y bizarre mais je ne sais pas comment faire sans cela. – andandandand

+0

+1 La suggestion est très bonne. Si ça n'a pas marché, ça veut dire que tu as foiré quelque chose. Faites-le correctement, et vos courbes s'afficheront bien. –

+0

@omgzor: Avez-vous débogué les valeurs qui arrivent lorsque vous cliquez sur l'écran? Vérifiez quelles sont les valeurs pour les emplacements connus (c.-à-d. En haut à gauche devrait être approximativement 0, 0 etc.).Cela vous aidera à trouver le problème. Le débogage est roi pour trouver ce genre de problème :) – Goz

0

Il y a beaucoup de problèmes dans votre code:

  1. un coup d'oeil ce que glutReshapeFunc ne
  2. la fonction myDisplay doit rendre l'image, et des tampons d'échange (si vous faites double buffering)
  3. toutes les autres fonctions devraient appeler glutPosRedisaply