PDA

View Full Version : Problem in drawing Bezier curve using Opengl evaluators



virtualchetan
07-17-2003, 12:42 PM
Dear All,

I am trying to draw a bezier curve using opengl evaluators.
Please see the attached 'test.C' file.

It fails to draw the curve if:

1) No. of control points, which I pass to the glMap1f(..) function is more than 8.
(mNoOfPoints >= 8)

OR

2) The 2D float array which holds the control point co-ordinates is dynamically allocated.
(i.e. If I use "float **mControlPoint" and allocate memory dynamically, instead of using "mControlPoint[8][3]").

Can you please tell me what the problem is.

- Chetan

#include <iostream.h>
#include <unistd.h>

#include <GL/glut.h>
#include <stdlib.h>

void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
// glShadeModel(GL_FLAT);
// glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
// glEnable(GL_MAP1_VERTEX_3);
// Setup the OpenGL display
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glEnable(GL_TEXTURE_2D);
}

void display(void)
{
///////////////////////////////////////
int mNoOfPoints = 8;//11

GLfloat mControlPoint[11][3] =
{
{ 518, 150, 0}, { 420, 92, 0}, { 369, 99, 0}, { 240, 81, 0},
{ 213, 78, 0}, { 206, 77, 0}, { 178, 81, 0}, { 158, 85, 0},
{ 111, 101, 0}, { 77, 113, 0}, { 70, 115, 0}
};
/*
GLfloat **mControlPoint;
mControlPoint = new GLfloat *[mNoOfPoints];
for(int i = 0; i < mNoOfPoints; i++)
mControlPoint[i] = new GLfloat[3];

for (int i = 0; i < mNoOfPoints; i++)
{
mControlPoint[i][0] = mPoint[i][0];
mControlPoint[i][1] = mPoint[i][1];
mControlPoint[i][2] = mPoint[i][2];
}
*/
///////////////////////////////////////
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);

// for(int i = 0; i < mNoOfPoints; i++)
// cout<<i<<" "<<mControlPoint[i][0]<<" "<<mControlPoint[i][1]<<" "<<mControlPoint[i][2]<<"\n";

glPushMatrix();

//draw Bezier
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, mNoOfPoints, &mControlPoint[0][0]);
glEnable(GL_MAP1_VERTEX_3);

glBegin(GL_LINE_STRIP);
for (long i = 0; i <= 100; i++)
{
glEvalCoord1d( (GLdouble) (i / 100.0));
}
glEnd();

glDisable(GL_MAP1_VERTEX_3);

//control points
glPointSize(5.0);
glBegin(GL_POINTS);
for(int i = 0; i < mNoOfPoints; i++)
glVertex3fv(&mControlPoint[i][0]);
glEnd();

glPopMatrix();

glFlush();
glutSwapBuffers();
}

void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, 0.0, 10.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
}
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc (keyboard);
glutMainLoop();
return 0;
}

Xmas
07-17-2003, 03:01 PM
Originally posted by virtualchetan:
It fails to draw the curve if:

1) No. of control points, which I pass to the glMap1f(..) function is more than 8.
(mNoOfPoints >= 8)
GL_MAX_EVAL_ORDER is usually 8. And that's enough for almost anything. I get the feeling you don't want an >8th order polynomial but a curve with more than 8 control points. If you really need that, you have to write the evaluation function for yourself. Or use several curves which are continuous (reusing control points)




OR

2) The 2D float array which holds the control point co-ordinates is dynamically allocated.
(i.e. If I use "float **mControlPoint" and allocate memory dynamically, instead of using "mControlPoint[8][3]").

Can you please tell me what the problem is.

I can.


GLfloat **mControlPoint;
mControlPoint = new GLfloat *[mNoOfPoints];
for(int i = 0; i < mNoOfPoints; i++)
mControlPoint[i] = new GLfloat[3];

See, you have double indirection here. If you define your array as float mControlPoint[8][3], you have one block of 24 float values.
If you do it like shown above, you have a block of eight pointers each pointing at three float values. That's guaranteed to fail.

You can only allocate multidimensional arrays dynamically in C++ if all but one dimension is constant. And then you need a simple trick:

typedef float vector[3];
vector *array = new vector[insert numerical expression here];

[This message has been edited by Xmas (edited 07-17-2003).]