Reputation: 291
im learning to use openGL and iv been told that because my wheel arches are concave i have to tessellate them. So here is my code for the front wheel arch...
GLdouble car[7][2] = { {-1.93,0.3}, {-1.95,0.4}, {-2.2,0.6}, {-2.6,0.6}, {-2.82,0.4}, {-2.8,0.3}, {-2.78,0.0} };
GLUtesselator *tess = gluNewTess(); // create a tessellator
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureLib[textureindex]);
glBegin(GL_POLYGON);
glTexCoord2f( 0.0 , 0.0 ); glVertex2f(-1.0 , 0.0 );
glTexCoord2f(-0.97, 0.0 ); glVertex2f(-1.97, 0.0 );
// Wheel arch
gluTessBeginContour(tess);
{
gluTessVertex(tess, car[0], car[0]);
gluTessVertex(tess, car[1], car[1]);
gluTessVertex(tess, car[2], car[2]);
gluTessVertex(tess, car[3], car[3]);
gluTessVertex(tess, car[4], car[4]);
gluTessVertex(tess, car[5], car[5]);
gluTessVertex(tess, car[6], car[6]);
}
gluTessEndContour(tess);
And the car looks like this:
{i know the texturing is wrong atm too) but as you can see the front wheel arch hasnt changed even with the tessellation, so i guess im tessellating wrong.. or need to tessellate more of it.. or something? if someone could please help me with this massive problem im having with the wheel arches and rectify it i would be eternally gratefully as i have been struggling to get past this point for a while. thanks :)
The whole drawBody function code can be found here: http://pastebin.com/s9RpzMsd
Update: Thanks for all the help: my object now looks like this thanks to the tessellation help. Now just to texture :)
Update 2: Ok so I used the same code roughly as PeterT suggested and this is what it ended up (had to make changes for it to compile. Point it out if its wrong)
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureLib[textureindex]);
GLUtesselator *tess = gluNewTess(); // create a tessellator
gluTessCallback(tess, GLU_TESS_VERTEX,
(void (__stdcall *) ()) &putvertex);
gluTessCallback(tess, GLU_TESS_BEGIN,
(void (__stdcall *) ()) &glBegin);
gluTessCallback(tess, GLU_TESS_END,
(void (__stdcall *) ()) &glEnd);
gluTessBeginPolygon(tess, NULL);
gluTessBeginContour(tess);
for(int i=0; i<29;i++)
gluTessVertex(tess, car[i], car[i]);
//call gluTessVertex for EVERY vertex in the polygon here
gluTessEndContour(tess);
gluTessEndPolygon(tess);
glDisable(GL_TEXTURE_2D);
With the putvertex code being:
void CALLBACK putvertex(GLdouble *verts)
{
//filled according to you texture coordinates:
GLdouble scalefacx = 1.0;
GLdouble scalefacy = 1.0;
GLdouble offsetx = -1.0;
GLdouble offsety = 0.0;
glVertex2dv(verts);
glTexCoord2d(verts[0]*scalefacx - offsetx,verts[1]*scalefacy - offsety);
}
It then looks like this:
Have i gone wrong somewhere? :/
Thanks for all your help, the final image looks like this:
Again thanks for all your help! Especially PeterT :)
Upvotes: 2
Views: 4703
Reputation: 8284
You can't just tessellate part of the polygyon and it'll work, you need to tessellate the whole polygon, something like this:
//fix for windows C++:
#ifndef CALLBACK
#define CALLBACK
#endif
tobj = gluNewTess();
gluTessCallback(tobj, GLU_TESS_VERTEX,
(GLvoid (CALLBACK*) ()) &glVertex3dv);
gluTessCallback(tobj, GLU_TESS_BEGIN,
(GLvoid (CALLBACK*) ()) &glBegin);
gluTessCallback(tobj, GLU_TESS_END,
(GLvoid (CALLBACK*) ()) &glEnd);
gluTessBeginPolygon(tobj, NULL);
gluTessBeginContour(tobj);
for(int i=0; i<7;i++)
gluTessVertex(tobj, car[i], car[i]);
//call gluTessVertex for EVERY vertex in the polygon here
gluTessEndContour(tobj);
gluTessEndPolygon(tobj);
Also, you need to specify all 3 components of the vertices as GLdouble
. So it would be something like this (still missing some vertices of course):
GLdouble car[7][3] = { {-1.93,0.3,0.0}, {-1.95,0.4,0.0}, {-2.2,0.6,0.0}, {-2.6,0.6,0.0}, {-2.82,0.4,0.0}, {-2.8,0.3,0.0}, {-2.78,0.0,0.0} };
In order to give every vertex a texture coordinate, you need to write your own function that takes a void *
(which will contain a pointer to the x,y,z coordinates of the vertex) and calls glVertex
and glTexCoord
.
Also you should avoid doing tesselation every frame, so you should either save the calls between gluTessBeginPolygon
and gluTessEndPolygon
in a Display list, or better yet have your GLU_TESS_VERTEX
function save the vertices in a VBO.
You might also have to define the GLU_TESS_COMBINE
callback, look here and here for details and more sample code.
edit2: Actually texturing is not quite so easy. This is some old deprecated code, that probably still works for you but is very unreliable especially if you use shaders. For a more modern version, look at this Thread. You should remove the glTexCoord2d()
calls and this has to go into the draw function:
//adjust these values to the object/texture size
GLfloat scalex = 1.0;
GLfloat scaley = 1.0;
GLfloat offsetx= 0.0;
GLfloat offsety= 0.0;
//GLdouble gens[4] = {1.0,0.0,0.0,0.0};
//GLdouble gent[4] = {0.0,1.0,0.0,0.0};
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glTexGend(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGend(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
//glTexGendv(GL_S,GL_OBJECT_PLANE,gens);
//glTexGendv(GL_T,GL_OBJECT_PLANE,gent);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(scalex,scaley,1.0f);
glTranslatef(offsetx,offsety,0.0);
//do the normal rendering
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
...
Also, remember that tessellating every frame is still not a good idea for anything but small tests, rather using it together with display list or VBOs as stated previously would be more effective.
Upvotes: 2
Reputation: 162164
gluTesselator will not make one single convex polygon from a concave polygon, because that's mathematically impossible. It emits multiple primitive groups (GL_POLYGON, GL_TRIANGLE, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN), and that's what you need to pass to OpenGL. Add tesselator callbacks to glBegin and glEnd as well.
Upvotes: 0