Question

I have a class called Polygon, in which I'm trying to render a tesselated polygon.

I have a method inside this class, called render, and several methods to draw my Polygon.

Those are, among others:

public class Polygon : public Entity
{
protected:
...
public:
    bool render();
    GLdouble* NewVector(GLdouble x, GLdouble y);
    void CALLBACK BeginCallback(GLenum type);
    void CALLBACK EndCallback();
    void CALLBACK VertexCallback(GLvoid *vertex);
    void CALLBACK CombineCallback(GLdouble coords[3], GLdouble *data[4], GLfloat weight[4], GLdouble **dataOut);
    void CALLBACK ErrorCallback(GLenum errorCode);
    };

And inside my method render I'm trying to register the gluTessCallback callbacks for BeginCallback, EndCallback and so on...

gluTessCallback(tess, GLU_TESS_BEGIN, (void(*)())&this->BeginCallback);

But this is giving me a compilation error,

error C2276: '&' : illegal operation on bound member function expression

I need to be this methods (from the current instance) since I'm needing to create and free some instance values in them.

Anyone can help me?

Was it helpful?

Solution

With GLU_TESS_*_DATA, the user-specified data may be used for "per-polygon" data.

Use private static member functions as callbacks and pass in your instance pointer through user_data.

Inside each callback you can static_cast<> the user_data pointer to your Polygon type and manipulate the resulting instance as desired.

Something like this:

class Poly
{
public:
    Poly( vector< dvec3 >& poly )
    {
        GLUtesselator* tess = gluNewTess();
        gluTessCallback( tess, GLU_TESS_BEGIN,          (GLvoid (CALLBACK *)()) Poly::begin       );
        gluTessCallback( tess, GLU_TESS_EDGE_FLAG,      (GLvoid (CALLBACK *)()) Poly::edgeFlag    );
        gluTessCallback( tess, GLU_TESS_END,            (GLvoid (CALLBACK *)()) Poly::end         );
        gluTessCallback( tess, GLU_TESS_VERTEX_DATA,    (GLvoid (CALLBACK *)()) Poly::vertexData  );
        gluTessCallback( tess, GLU_TESS_COMBINE_DATA,   (GLvoid (CALLBACK *)()) Poly::combineData );
        gluTessNormal( tess, 0.0, 0.0, 1.0 );

        gluTessBeginPolygon( tess, (void*)this );
        gluTessBeginContour( tess );

        for( size_t i = 0; i < poly.size(); ++i )
        {
            gluTessVertex( tess, &poly[i][0], &poly[i] );
        }

        gluTessEndContour( tess );
        gluTessEndPolygon( tess );

        gluDeleteTess(tess);

        for( size_t i = 0; i < mCombined.size(); ++i )
        {
            delete mCombined[i];
        }
        mCombined.clear();
    }

    void Render()
    {
        glBegin( GL_TRIANGLES );
        for( size_t i = 0; i < mTriangles.size(); ++i )
        {
            glVertex3dv( &mTriangles[i][0] );
        }
        glEnd();
    }

private:
    static void begin( GLenum type ) {}
    static void edgeFlag( GLboolean flag ) {}
    static void end() {}

    static void vertexData( void *vertex_data, void *polygon_data )
    {
        Poly& p = *static_cast< Poly* >( polygon_data );
        dvec3& pt = *static_cast< dvec3* >( vertex_data );
        p.mTriangles.push_back( pt );
    }

    static void combineData( GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **outData, void *polygon_data )
    {
        Poly& p = *static_cast< Poly* >( polygon_data );

        dvec3* newVert = new dvec3();
        (*newVert)[0] = coords[0];
        (*newVert)[1] = coords[1];
        (*newVert)[2] = coords[2];

        p.mCombined.push_back( newVert );
        *outData = newVert;
    }

    vector< dvec3 > mTriangles;
    vector< dvec3* > mCombined;
};

OTHER TIPS

You cannot get a reference to a member function pointer in C++ without capturing the this value of the current object.

Put another way, when you invoke a member function in C++ you implicitly pass this as an argument to the function--without specifying what this is you cannot invoke a member function (and a regular function pointer doesn't have room to store the this reference.

You can handle this a couple of ways; make your callback function static (which doesn't require an object reference) or you can move it outside the class altogether.

If you're using C++11 you could use a lambda expression but I'm not sure of the implications of passing one to this call; I believe it should be okay.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top