2017-02-12 2 views
-1

私は複雑なポリゴンをテッセレーションするためにgluテッセレーションを使用します。以下に簡略化したコードを示します。gluTessEndPolygon()でglutesselatorが常にクラッシュする

それは、常にエラーでgluTessEndPolygon(GLUtessobj)でクラッシュ:

エラー:0xc0000005で:アクセス違反が場所0x57783b39を読みました。

ポリゴンの点数が小さい場合(< 100)にコードが機能します。

私は理由を理解できません。すぐに奇数として私を打つ

typedef boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> pt; 
typedef boost::geometry::model::polygon<pt> Polygon; 
typedef boost::geometry::model::ring<pt> Ring; 
vector<Polygon> g_myPolys; 


// ------Static variables used in glu tessellation------ 
static GLUtesselator *GLUtessobj; 
static unsigned int s_gltri_type; 
static int s_tess_orient; 
static int s_cur_pt_idx; 
// Create an array to hold pointers to allocated vertices created by "combine" callback, 
// so that they may be deleted after tessellation. 
static std::vector<GLdouble*>  s_combineVertexArray; 

// Store tessellated results 
static std::vector<double> s_vecTriVerts; // Store area objects' tessellated triangle(triangle fan, triangle strip and triangles) vertices. 
static std::vector<int> s_vecTriStripVertCnts; // Store every triangle strips' start indices in m_vecTriVerts. 
static std::vector<int> s_vecTriStripFirstIdx; // Store every triangle strips' vertex count start from its start index. 

static std::vector<int> s_vecTriFanVertCnts; // Store every triangle fans' start indices in m_vecTriVerts. 
static std::vector<int> s_vecTriFanFirstIdx; // Store every triangle fans' vertex count start from its start index. 

static std::vector<int> s_vecTrisVertCnts; // Store every triangles' start indices in m_vecTriVerts. 
static std::vector<int> s_vecTrisFirstIdx; // Store every triangles' vertex count start from its start index. 

static int s_cur_tri_fans_vert_cnt; 
static int s_cur_tri_strips_vert_cnt; 
static int s_cur_tris_vert_cnt; 

static std::vector<double*> s_vecTmp; 

void beginCallback(GLenum which) 
{ 
    s_gltri_type = which; 
    switch (s_gltri_type) 
    { 
    case GL_TRIANGLE_FAN: 
     s_vecTriFanFirstIdx.push_back(s_cur_pt_idx); 
     s_cur_tri_fans_vert_cnt = 0; 
     break; 
    case GL_TRIANGLE_STRIP: 
     s_vecTriStripFirstIdx.push_back(s_cur_pt_idx); 
     s_cur_tri_strips_vert_cnt = 0; 
     break; 
    case GL_TRIANGLES: 
     s_vecTrisFirstIdx.push_back(s_cur_pt_idx); 
     s_cur_tris_vert_cnt = 0; 
     break; 
    } 
} 


void vertexCallback(GLvoid *vertex) 
{ 
    GLdouble *pv = (GLdouble *) vertex; 
    s_vecTriVerts.push_back(pv[0]); 
    s_vecTriVerts.push_back(pv[1]); 

    s_cur_pt_idx ++; 

    switch (s_gltri_type) 
    { 
    case GL_TRIANGLE_FAN: 
     s_cur_tri_fans_vert_cnt ++; 
     break; 
    case GL_TRIANGLE_STRIP: 
     s_cur_tri_strips_vert_cnt ++; 
     break; 
    case GL_TRIANGLES: 
     s_cur_tris_vert_cnt ++; 
     break; 
    } 
} 

void combineCallback(GLdouble coords[3], 
    GLdouble *vertex_data[4], 
    GLfloat weight[4], GLdouble **dataOut) 
{ 
    GLdouble *vertex = (GLdouble *)malloc(6 * sizeof(GLdouble)); 

    vertex[0] = coords[0]; 
    vertex[1] = coords[1]; 
    vertex[2] = coords[2]; 
    vertex[3] = vertex[4] = vertex[5] = 0.0; 

    *dataOut = vertex; 

    s_combineVertexArray.push_back(vertex); 
} 

void endCallback() 
{ 
    switch (s_gltri_type) 
    { 
    case GL_TRIANGLE_FAN: 
     s_vecTriFanVertCnts.push_back(s_cur_tri_fans_vert_cnt); 
     break; 
    case GL_TRIANGLE_STRIP: 
     s_vecTriStripVertCnts.push_back(s_cur_tri_strips_vert_cnt); 
     break; 
    case GL_TRIANGLES: 
     s_vecTrisVertCnts.push_back(s_cur_tris_vert_cnt); 
     break; 
    } 
} 

void errorCallback(GLenum errorCode) 
{ 
    const GLubyte *estring; 
    estring = gluErrorString(errorCode); 
    printf ("Tessellation Error: %s\n", estring); 
} 

void Tessellate() 
{ 
    // Create tessellate object 
    GLUtessobj = gluNewTess(); 

    // Register the callbacks 
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (void (__stdcall*)())&beginCallback); 
    gluTessCallback(GLUtessobj, GLU_TESS_VERTEX, (void (__stdcall*)())&vertexCallback); 
    gluTessCallback(GLUtessobj, GLU_TESS_END,  (void (__stdcall*)())&endCallback); 
    gluTessCallback(GLUtessobj, GLU_TESS_COMBINE, (void (__stdcall*)())&combineCallback); 
    gluTessCallback(GLUtessobj, GLU_TESS_ERROR, (void (__stdcall*)())&errorCallback); 

    gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE); 

    gluTessBeginPolygon(GLUtessobj, NULL); 
    gluTessBeginContour(GLUtessobj); 

    Polygon pp = g_myPolys[0]; 
    for (int i = 0; i < pp.outer().size(); i ++) 
    { 
     GLdouble *p = new GLdouble[3]; 
     s_vecTmp.push_back(p); 

     p[0] = pp.outer()[i].get<0>(); 
     p[1] = pp.outer()[i].get<1>(); 
     p[2] = 0.0; 

     gluTessVertex(GLUtessobj, p, p) ; 
    } 

    gluTessEndContour(GLUtessobj); 
    gluTessEndPolygon(GLUtessobj); 

    gluDeleteTess(GLUtessobj); 

    for (int i = 0; i < s_vecTmp.size(); i ++) 
     delete[] s_vecTmp[i]; 
    s_vecTmp.clear(); 

    // Free up any "Combine" vertices created 
    for(unsigned int i = 0; i < s_combineVertexArray.size(); i++) 
     free (s_combineVertexArray[i]); 
    s_combineVertexArray.clear(); 
} 
+0

GLUテセレーターは古代であり、現代ドライバーがそれを徹底的にテストしなければ私は驚かないでしょう。 – SurvivalMachine

+0

@SurvivalMachine私は古いバージョンのOpenGLをコンパイルする必要があります。 OpenGLのバージョンが4.0未満の方が良い方法はありますか? –

+0

['libtess2'](https://github.com/memononen/libtess2)?また、[mcve]で編集します。 – genpfault

答えて

1

ことの一つは、あなたがそこに__stdcallにキャストを行うこと、です。

gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (void (__stdcall*)())&beginCallback); 

なぜあなたはそれをやっていますか?あなたのコンパイラが互換性のない呼び出し規約を訴えている場合、最後に行うべきことは呼び出し規約をキャストすることです。呼び出し規約を打つだけで、絶望と恐怖が待っています。ポインタをキャストするのは悪い考えです(C++のキャストで/からvoid*までは大丈夫ですが、それだけです)。

そして、あなたがポインタで行ういくつかの奇妙なことがあります。たとえば、std::vectorと手動管理メモリ(new GLdouble[3])を混在させているとします。真剣に、なぜ?

あなたのデータ構造を単純化し、そのポインタジャグリングをクリーンアップすることを強くお勧めします。ほとんどの場合、コードのどこかに範囲外バッファが書き込まれている可能性がありますが、正確にどこを参照するのは難しいです。

+0

コールバックの呼び出し規約とgluTessCallback第3パラメータは同一ではなく、問題が発生します。私は呼び出し規約にあまり注意を払わず、メモリ管理に問題があると考えました。 –

関連する問題