I am trying to color a NURBS surface based on proximity to control points. That is, I would like each control point to have a corresponding color and the surface to be colored based on these colors.
I have gotten the NURBS surface to display and can color the whole thing with a simple glColor* call. However, when I try passing a glNurbsSurface call with GL_MAP2_COLOR_4 in addition to GL_MAP2_VERTEX_3 nothing changes. I’ve read that you can pass glNurbsSurface any 2d evaluator type such as GL_MAP2_COLOR_4, but can only find examples of GL_MAP2_VERTEX_3, GL_MAP2_TEXTURE_COORD2_2, and GL_MAP2_NORMAL. So I really don’t have any idea how to use GL_MAP2_COLOR_4. Is the idea that vertex control point number 7 will be associated with color control point number 7? Or am I thinking about this the totally wrong way?
Here’s the relevant code:
Generates the control points array for a rectangular NURBS. Later, I pass it through a method to change the heights.
public float[] genControlPointsGrid(int rows, int cols){
float[] ctrlPts = new float[rows*cols*3];
for(int u=0;u<cols;u++){
for(int v=0;v<rows;v++){
float x = 2f*(u-cols/2f);
float y = 2f*(v-rows/2f);
ctrlPts[u*rows*3+v*3+0] = x;
ctrlPts[u*rows*3+v*3+1] = y;
}
}
return ctrlPts;
}
Generates what I think should be the color control points.
public float[] genColorControlPointsGrid(int rows, int cols){
float[] colorCtrlPts = new float[rows*cols*4];
for(int c=0;c<cols;c++){
for(int r=0;r<rows;r++){
float red = ((float)r)/((float)rows);
//float red = 1.0f;
float green = ((float)c)/((float)cols);
//float green = 1.0f;
float blue = 0.0f;
float alpha = 1.0f;
colorCtrlPts[c*rows*4 + c*4 + 0] = red;
colorCtrlPts[c*rows*4 + c*4 + 1] = green;
colorCtrlPts[c*rows*4 + c*4 + 1] = blue;
colorCtrlPts[c*rows*4 + c*4 + 1] = alpha;
}
}
return colorCtrlPts;
}
Generates the knots vector. I use the same knots vector for the vertex control points and the color control points.
public float[] genUniformKnots(int order, int numCtrlPts){
float[] k = new float[order+numCtrlPts];
float interval = 1.0f/(numCtrlPts-order+1);
for(int i = 0; i<order; i++){
k[i]=0.0f;
k[order+numCtrlPts-i-1] = 1.0f;
}
for(int i = order; i<numCtrlPts;i++)
k[i]=k[i-1]+interval;
return k;
}
Draw the actual nurbs surface. This works, except it doesn’t color the surface. The surface takes the color of the last glColor* call.
Also, if I switch the order of the glNurbsSurface calls, the NURBS surface does not display.
public void drawGridNURBS(GL gl, GLU glu, float[] ctrlPts, float[] rowKnots, float[] colKnots, float[] colorCtrlPts){
glu.gluBeginSurface(theNurb);
glu.gluNurbsSurface(theNurb,
colKnots.length, colKnots,
rowKnots.length, rowKnots,
(rowKnots.length-4)*4,
4,
colorCtrlPts,
4,4,
gl.GL_MAP2_COLOR_4);
glu.gluNurbsSurface(theNurb,
colKnots.length, colKnots,
rowKnots.length, rowKnots,
(rowKnots.length-4)*3,
3,
ctrlPts,
4, 4,
gl.GL_MAP2_VERTEX_3);
glu.gluEndSurface(theNurb);
}
The call to draw the NURBS:
drawGridNURBS(gl, glu, genControlPointsGrid(51,51), genUniformKnots(4,51), genUniformKnots(4,51), genColorControlPointsGrid(51,51));
Possibly related part of init
gl.glColorMaterial(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT_AND_DIFFUSE);
gl.glEnable(gl.GL_COLOR_MATERIAL);
gl.glEnable(gl.GL_LIGHTING);
gl.glEnable(gl.GL_LIGHT0);
gl.glDepthFunc(gl.GL_LEQUAL);
gl.glEnable(gl.GL_DEPTH_TEST);
gl.glEnable(gl.GL_AUTO_NORMAL);
gl.glEnable(gl.GL_NORMALIZE);
gl.glEnable(gl.GL_MAP2_COLOR_4);
theNurb = glu.gluNewNurbsRenderer();
Apologies if I’m missing something obvious. I’ve only recently learned how NURBS work. Also, I realize that JOGL does not fully support NURBS yet. Could this be one of the missing features? If so, any ideas for a workaround?