Question

I am creating a program that allows me to plot points in 3 space, connects them using a Catmull-Rom Spline, and then draws a cylinder around the Spline. I am using GL_TRIANGLES_STRIP to connect circles of points drawn around the Spline at short intervals, to hopefully connect them all together into a Cylinder around the Spline.

I have managed to draw complete circles of points at these intervals, using GL_POINTS, and orientate them correctly to the line with regards to a Frenet Frame. Unfortunately, to use GL_TRIANGLE_STRIP, I believe I need to plot the points one at a time between a set of two circles of points.

The problem I am having, is that the glMultMatrix doesn't seem to work when inside a glBegin. The code below will draw a circle of points, but at the origin, and the glMultMatrix, which I use to translate and orientate the circle of points, doesn't seem to apply when inside the glbegin. Is there a solution to this?

  //The matrixes that are applied to the circle of points
  GLfloat M1[16]={
    N1.x(),N1.y(),N1.z(),0,
    B1.x(),B1.y(),B1.z(),0,
    T1.x(),T1.y(),T1.z(),0,
    fromPoint->x,fromPoint->y,fromPoint->z,1
  };

  GLfloat M2[16]={
    N2.x(),N2.y(),N2.z(),0,
    B2.x(),B2.y(),B2.z(),0,
    T2.x(),T2.y(),T2.z(),0,
    toPoint->x,toPoint->y,toPoint->z,1
  };

  glBegin(GL_TRIANGLE_STRIP);
  GLfloat x, y;
  GLfloat radius = 0.4f;
  GLint pointCount = 180;
  for (GLfloat theta = 0; theta < 2*M_PI; theta += (2*M_PI)/pointCount) {
    x = radius * cos(theta);
    y = radius * sin(theta);

    // Now push a matrix, multiply it, draw a point and pop the matrix
    glPushMatrix();
    glMultMatrixf(& M1[0]);
    // Draw the point here
    glVertex3f(x, y, 0);
    glPopMatrix();

    // Do the same again for the second section
    glPushMatrix();
    glMultMatrixf(& M2[0]);
    glVertex3f(x, y, 0);
    glPopMatrix();
  }
  glEnd();
Was it helpful?

Solution

The problem I am having, is that the glMultMatrix doesn't seem to work when inside a glBegin

Unsurprising:

Only a subset of GL commands can be used between glBegin and glEnd. The commands are glVertex, glColor, glSecondaryColor, glIndex, glNormal, glFogCoord, glTexCoord, glMultiTexCoord, glVertexAttrib, glEvalCoord, glEvalPoint, glArrayElement, glMaterial, and glEdgeFlag. Also, it is acceptable to use glCallList or glCallLists to execute display lists that include only the preceding commands. If any other GL command is executed between glBegin and glEnd, the error flag is set and the command is ignored.

glMultMatrix() before glBegin():

//The matrixes that are applied to the circle of points
GLfloat M1[16]=
{
    N1.x(),N1.y(),N1.z(),0,
    B1.x(),B1.y(),B1.z(),0,
    T1.x(),T1.y(),T1.z(),0,
    fromPoint->x,fromPoint->y,fromPoint->z,1
};

GLfloat M2[16]=
{
    N2.x(),N2.y(),N2.z(),0,
    B2.x(),B2.y(),B2.z(),0,
    T2.x(),T2.y(),T2.z(),0,
    toPoint->x,toPoint->y,toPoint->z,1
};

GLfloat x, y;
GLfloat radius = 0.4f;
GLint pointCount = 180;
for (GLfloat theta = 0; theta < 2*M_PI; theta += (2*M_PI)/pointCount) 
{
    x = radius * cos(theta);
    y = radius * sin(theta);

    // Now push a matrix, multiply it, draw a point and pop the matrix
    glPushMatrix();
    glMultMatrixf(& M1[0]);
    // Draw the point here
    glBegin(GL_POINTS);
    glVertex3f(x, y, 0);
    glEnd();
    glPopMatrix();

    // Do the same again for the second section
    glPushMatrix();
    glMultMatrixf(& M2[0]);
    glBegin(GL_POINTS);
    glVertex3f(x, y, 0);
    glEnd();
    glPopMatrix();
}

Or apply the transforms client-side and hand OpenGL a big block 'o vertices to render in one go.

EDIT: Or pull those matrix multiplies outside the loop entirely:

GLfloat x, y;
GLfloat radius = 0.4f;
GLint pointCount = 180;

glPushMatrix();
glMultMatrixf(& M1[0]);
glBegin(GL_POINTS);
for (GLfloat theta = 0; theta < 2*M_PI; theta += (2*M_PI)/pointCount) 
{
    x = radius * cos(theta);
    y = radius * sin(theta);

    // Draw the point here
    glVertex3f(x, y, 0);
}
glEnd();
glPopMatrix();

glPushMatrix();
glMultMatrixf(& M2[0]);
glBegin(GL_POINTS);
for (GLfloat theta = 0; theta < 2*M_PI; theta += (2*M_PI)/pointCount) 
{
    x = radius * cos(theta);
    y = radius * sin(theta);

    // Draw the point here
    glVertex3f(x, y, 0);
}
glEnd();
glPopMatrix();

OTHER TIPS

you can also use a vertex array to hold all info and then push the data to openGL:

GLFloat[] points = new GLFloat[3*pointCount];

for (GLfloat theta = 0; theta < 2*M_PI; theta += (2*M_PI)/pointCount) 
{
    points[0+off] = radius * cos(theta);
    points[1+off] = radius * sin(theta);
    points[2+off] = 0;
    off+=3;
}

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, points);

glPushMatrix();
glMultMatrixf(& M1[0]);
glDrawArrays(GL_POINTS, 0, pointCount);
glPopMatrix();

glPushMatrix();
glMultMatrixf(& M2[0]);
glDrawArrays(GL_POINTS, 0, pointCount);
glPopMatrix();

glDisableClientState(GL_VERTEX_ARRAY);
delete[] points;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top