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;
}
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
+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. –
@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