Pregunta

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?

¿Fue útil?

Solución

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;
};

Otros consejos

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top