glutesselator всегда вылетает при gluTessEndPolygon ()

Я использую тесселяцию глю для тесселяции сложных полигонов. Упрощенный код приведен ниже.

Это всегда падает на 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();
}

-1

Решение

Одна вещь, которая сразу кажется мне странной, это то, что вы делаете бросок к __stdcall там.

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

Зачем ты это делаешь? Если ваш компилятор жалуется на несовместимые соглашения о вызовах, то последнее, что вы должны сделать, это привести соглашение о вызовах. Только отчаяние и ужас ждут, если вы разыгрываете соглашение о вызовах. Уже плохая идея приводить указатели (в C ++ приведение из / в void* вроде нормально, но это все).

И затем есть несколько других странных вещей, которые вы делаете с указателями. Например, вы смешиваете std::vector с управляемой вручную памятью (new GLdouble[3]). Серьезно, почему ?!

Я настоятельно рекомендую вам упростить ваши структуры данных и очистить этот жонглирование указателя. Скорее всего, в вашем коде есть записи в буфер за пределами границ, но трудно понять, где именно.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]