简体   繁体   中英

How to draw a Bezier curve with C++ in OpenGL using floating point values

I am trying to draw a Bezier curve in OpenGL using floating point values. I have tried using many different code examples. My current code below, runs ,but does not show the curve on screen. The usual way to draw Bezier curves are with integer values, which means using the GLUORTHO2D() function for drawing the curve. But I want to draw a curve using floating point values. Such as x range(-1,1) and y range(-1,1) .

like if x=(500) then consider it (-1 to 1) and if y=(800) then consider it (-1,1) .

I have already tried using integer values and it worked for me. my code using integer values is below:

#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
int X1[3]={20,25,20}, Y1[3]={5,24,38};  //first point(x1[0],y1[0])    second(x1[1],y1[1]) third(x1[2],y1[2])

void myInit()
{
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(1.0,0.0,0.0);
glPointSize(8.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,128.0,0.0,96.0);
}
//p(t)=(1-t)^3*p0+3t(1-t)^2*p1+3t^2(1-t)p2+t^3p3
float getNextBezierPointX(float t)
{
float x=0.0;

for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
    c = 1;
else
{
    c = ctrlPointsCount-1;
}
x +=  c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsX[i];
}


return x;
}

float getNextBezierPointY(float t)
{
float y=0.0;

for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
    c = 1;
else
{
    c = ctrlPointsCount-1;
}
y +=  c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsY[i];
}



return y;
}
void drawline()
{
// draw control points using red color
for(int i=0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using          cubic bezier curve formula
float oldX=ctrlPointsX[0], oldY=ctrlPointsY[0];
for(double t = 0.0;t <= 1.0; t += 0.01) {

float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();

oldX = x;
oldY = y;
}
}

void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
ctrlPointsCount=3;
for(int i=0;i<3;i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();


glFlush();
}


int main(int argc, char *argv[])
{

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(640,480);
glutInitWindowPosition(100,150);
glutCreateWindow("Bezier Curve");
glutDisplayFunc(myDisplay);
myInit();
glutMainLoop();
return 0;
}

But when i tried using floating point values , it does not work for me. It does not show the curved line on screen. My code using floating point values is below:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;
#define CTRL_COUNT 100

int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {           0.946875, 0.884375, 0.946875 };
//Initializes 3D rendering
void initRendering() {
glEnable(GL_DEPTH_TEST); 
}
float getNextBezierPointX(float t)
{
float x = 0.0;

for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
    c = 1;
else
{
    c = ctrlPointsCount - 1;
}
x += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) *        ctrlPointsX[i];
}

return x;
}
float getNextBezierPointY(float t)
{
float y = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
    c = 1;
else
{
    c = ctrlPointsCount - 1;
}
y += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) *        ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for (int i = 0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using           cubic bezier curve formula
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01)
        {
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}
float _angle = 0.0;
float _cameraAngle = 0.0;
float _ang_tri = 0.0;
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //Reset the drawing perspective
ctrlPointsCount = 3;
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glutSwapBuffers();
}
void update(int value) {
_angle += 2.0f;
if (_angle > 360) {
_angle -= 360;
}
_ang_tri += 2.0f;
if (_ang_tri > 360) {
_ang_tri -= 360;
}
glutPostRedisplay(); //Tell GLUT that the display has changed
//Tell GLUT to call update again in 25 milliseconds
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
//Initialize GLUT

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1331, 641);
glutInitWindowPosition(0, 0);

//Create the window
glutCreateWindow("Our cg project");
initRendering();

//Set handler functions
glutDisplayFunc(drawScene);

glutReshapeFunc(handleResize);

glutTimerFunc(25, update, 0); //Add a timer

glClearColor(0.0, 0.7, 1.5,0.0);

glutMainLoop();
return 0;
}

The problem is this here:

int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };

for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}

ctrlPointsX and ctrlPointsY can only hold integer values. So when you do ctrlPointsX[i] = X1[i] and ctrlPointsY[i] = Y1[i] you are converting the floats to integers, which will round them down. So all your controlPoints will be 0.

You have to declare the controlPoints arrays as type double too:

double ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };

This should fix your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM