2

Reading the manual page of the gluTessVertex(), the definition goes like this:

void gluTessVertex( GLUtesselator* tess, GLdouble * location, void * data);

I would imagine that the location is the vertex and for data, at least to me, it sounds like that would be a pointer to my C++ object so I can handle the callback properly.

data
    Specifies an opaque pointer passed back to the program with the vertex callback (as specified by gluTessCallback).

However, I see that all the examples I can find use their vertex pointer for both parameters and even in my implementation, it works only if I do that:

gluTessVertex(tobj, polygon->at(p).f_coordinates, polygon->at(p).f_coordinates);

If I don't do that, the coordinates in my output are quite random. Yet, that's hardly an opaque pointer if the GLUT interprets the data pointer as a vertex of positions...

So my question is: Am I misunderstanding the documentation or is the documentation incorrect?


List of callbacks as defined in the gluTessCallback are:

void beginData( GLenum type, void *polygon_data );
void edgeFlagData( GLboolean flag, void *polygon_data );
void vertexData( void *vertex_data, void *polygon_data );
void endData( void *polygon_data );
void combineData( GLdouble coords[3], void *vertex_data[4], 
                  GLfloat weight[4], void **outData, 
                  void *polygon_data );
void errorData( GLenum errno, void *polygon_data );

My functions are defined as such:

static void tess_callback_edge(GLboolean edge, font_impl * impl);
static void tess_callback_begin(GLenum type, font_impl * impl);
static void tess_callback_vertex(GLdouble const * vertex, font_impl * impl);
static void tess_callback_combine(
                                  GLdouble coords[3]
                                , GLdouble * vertex_data[4]
                                , GLfloat weight[4]
                                , GLdouble ** out_data
                                , font_impl * impl);
static void tess_callback_end(font_impl * impl);
static void tess_callback_error(GLenum errCode, font_impl * impl);
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • Your code (which you should include in the question) *does* expect a `font_impl*` in that position; I don’t see why a `double*` would work. You need to post a complete if trivial example. – Davis Herring May 09 '21 at 22:43
  • @DavisHerring I agree, I put `this` at first and it was not working. Once I put the pointer to the coordinates, it magically started working as expected. And pretty much all the working examples do that too. The [full implementation](https://github.com/m2osw/ftmesh/blob/main/ftmesh/font.cpp#L335) is on github and it's rather big so I put a link in the question. – Alexis Wilke May 09 '21 at 23:02
  • 1
    Ah, now I see: your callback takes the wrong number of arguments. Cast from `void*` inside your callback instead of using `reinterpret_cast` on the function itself to avoid such nonsense. – Davis Herring May 09 '21 at 23:53
  • 1
    I'm not too sure I follow. Just in case, I added the list of callbacks as documented and my versions. They all have the same types. The `reinterpret_cast` is mandatory unless I don't define the parameters of my functions (then I have to go get them on the stack _at random_, not a good solution). The definition of `_GLUfuncptr CallBackFunc` is `typedef void (GLAPIENTRYP _GLUfuncptr)(void);`. That's why I have to have a cast. – Alexis Wilke May 10 '21 at 00:35
  • 1
    Sorry, I missed two points here. Avoiding casts for callbacks is good advice in general, but you’re right here because multiple function pointer types are multiplexed onto the one `gluTessCallback`. I also overlooked that you were using the two-argument `_DATA` version. In that case, everything seems **correct** as written: the last argument to `glTessVertex` is the *first* argument to your `tess_callback_vertex`, which you require to be a pointer to the vertex coordinates. The other comes from `gluTessBeginPolygon`, which does use `this`. What’s the question? – Davis Herring May 10 '21 at 01:58
  • It’s still better to declare your functions as taking actual `void*` parameters, by the way: theoretically, because it’s undefined behavior to call through the wrong function type, and practically, because you might accidentally use a function type that isn’t ABI compatible. – Davis Herring May 10 '21 at 02:17
  • @DavisHerring The question is: What is the `data` argument to the `glTessVertex()` function? It sounds like it should be `this`, but it only works when I pass the `f_coordinates`. If it needs `f_coordinates`, the vertices, it's not _opaque_ as per the documentation... – Alexis Wilke May 10 '21 at 06:37
  • It needs whatever *your* callback needs (as its first argument). You (as is common) *made* that be the coordinates! – Davis Herring May 10 '21 at 06:45

1 Answers1

1

Its a bit confusing, but if you follow through the Mesa source code for example

https://gitlab.freedesktop.org/mesa/glu/-/blob/master/src/libtess/tess.c and render.c

The two parameters for vertexCallback are coming from different gluTess functions. By naming the parameters accordingly maybe this makes it clearer:

static void vertexCallback(GLvoid* vertexData, GLvoid* polygonData);

gluTessBeginPolygon(t,&polygonData);

gluTessVertex(t,coord,&vertexData);

This is why it's common to just pass the pointer to the vertex but you could also just supply anything and use it accordingly in the vertexCallback.

Giles Bathgate
  • 724
  • 6
  • 8