OpenGL тесселяция автомобиля из многоугольника - PullRequest
2 голосов
/ 09 января 2012

я учусь использовать openGL, и мне сказали, что из-за того, что мои колесные арки вогнуты, я должен их тесселяции. Так вот мой код для арки переднего колеса ...

GLdouble car[7][2] = { {-1.93,0.3}, {-1.95,0.4}, {-2.2,0.6}, {-2.6,0.6}, {-2.82,0.4}, {-2.8,0.3}, {-2.78,0.0} };
GLUtesselator *tess = gluNewTess(); // create a tessellator

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureLib[textureindex]);

glBegin(GL_POLYGON);

glTexCoord2f( 0.0 , 0.0 ); glVertex2f(-1.0 , 0.0 );
glTexCoord2f(-0.97, 0.0 ); glVertex2f(-1.97, 0.0 );

// Wheel arch
gluTessBeginContour(tess);
{
    gluTessVertex(tess, car[0], car[0]);
    gluTessVertex(tess, car[1], car[1]);
    gluTessVertex(tess, car[2], car[2]);
    gluTessVertex(tess, car[3], car[3]);
    gluTessVertex(tess, car[4], car[4]);
    gluTessVertex(tess, car[5], car[5]);
    gluTessVertex(tess, car[6], car[6]);
}
gluTessEndContour(tess);

И машина выглядит так:

car

{я знаю, что текстурирование тоже неправильно), но, как вы можете видеть, арка переднего колеса не изменилась даже при тесселяции, так что я думаю, что я тесселяции неправильно ... или нужно больше тесселяции .. или что-то еще? если бы кто-то мог помочь мне с этой огромной проблемой, которую я испытываю с колесными арками, и исправить ее, я был бы вечно благодарен, поскольку я изо всех сил пытался пройти этот момент некоторое время. спасибо :)

Весь код функции drawBody можно найти здесь: http://pastebin.com/s9RpzMsd

Обновление: спасибо за помощь: мой объект теперь выглядит вот так благодаря помощи тесселяции. Теперь просто на текстуру :)

car better

Обновление 2: Хорошо, поэтому я использовал примерно тот же код, который предложил PeterT, и на этом все закончилось (пришлось внести изменения для его компиляции. Укажите, если это не так)

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureLib[textureindex]);

GLUtesselator *tess = gluNewTess(); // create a tessellator

gluTessCallback(tess, GLU_TESS_VERTEX,
               (void (__stdcall *)  ()) &putvertex);
gluTessCallback(tess, GLU_TESS_BEGIN,
               (void (__stdcall *)  ()) &glBegin);
gluTessCallback(tess, GLU_TESS_END,
               (void (__stdcall *)  ()) &glEnd);


gluTessBeginPolygon(tess, NULL);
gluTessBeginContour(tess);
    for(int i=0; i<29;i++)
        gluTessVertex(tess, car[i], car[i]);
        //call gluTessVertex for EVERY vertex in the polygon here 
    gluTessEndContour(tess);
gluTessEndPolygon(tess);
glDisable(GL_TEXTURE_2D);

С кодом путвертекса:

void CALLBACK putvertex(GLdouble *verts)
{
//filled according to you texture coordinates:
GLdouble scalefacx = 1.0;
GLdouble scalefacy = 1.0;
GLdouble offsetx = -1.0;
GLdouble offsety = 0.0;
glVertex2dv(verts);
glTexCoord2d(verts[0]*scalefacx - offsetx,verts[1]*scalefacy - offsety);
}

Тогда это выглядит так:

car texture

Я где-то ошибся? : /

Спасибо за вашу помощь, окончательное изображение выглядит так:

car finished

Еще раз спасибо за вашу помощь! Особенно ПетерТ :)

Ответы [ 2 ]

2 голосов
/ 09 января 2012

Вы не можете просто тесселяции части полигона, и он будет работать, вам нужно тесселяции всего полигона, что-то вроде этого:

   //fix for windows C++:
   #ifndef CALLBACK
   #define CALLBACK
   #endif

   tobj = gluNewTess();
   gluTessCallback(tobj, GLU_TESS_VERTEX,
                   (GLvoid (CALLBACK*) ()) &glVertex3dv);
   gluTessCallback(tobj, GLU_TESS_BEGIN,
                   (GLvoid (CALLBACK*) ()) &glBegin);
   gluTessCallback(tobj, GLU_TESS_END,
                   (GLvoid (CALLBACK*) ()) &glEnd);

   gluTessBeginPolygon(tobj, NULL);
      gluTessBeginContour(tobj);
         for(int i=0; i<7;i++)
           gluTessVertex(tobj, car[i], car[i]);
         //call gluTessVertex for EVERY vertex in the polygon here 
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);

Кроме того, вам нужно указать все 3 компонентавершины как GLdouble.Таким образом, это было бы что-то вроде этого (все еще пропуская некоторые вершины, конечно):

GLdouble car[7][3] = { {-1.93,0.3,0.0}, {-1.95,0.4,0.0}, {-2.2,0.6,0.0}, {-2.6,0.6,0.0}, {-2.82,0.4,0.0}, {-2.8,0.3,0.0}, {-2.78,0.0,0.0} };

Чтобы дать каждой вершине координату текстуры, вам нужно написать свою собственную функцию, которая принимает void * (которыйбудет содержать указатель на координаты x, y, z вершины) и вызовет glVertex и glTexCoord.

Также следует избегать тесселяции в каждом кадре, поэтому следует либо сохранять вызовы между gluTessBeginPolygon и gluTessEndPolygon в списке отображения, или еще лучше, если ваша функция GLU_TESS_VERTEX сохраняет вершины в VBO.

Возможно, вам также потребуется определить обратный вызов GLU_TESS_COMBINE, посмотрите здесь и здесь для получения подробной информации и примера кода.

edit2: На самом деле текстурирование не так просто.Это старый устаревший код, который, вероятно, все еще работает для вас, но очень ненадежен, особенно если вы используете шейдеры.Для более современной версии посмотрите на эту тему .Вы должны удалить вызовы glTexCoord2d(), и это должно войти в функцию рисования:

//adjust these values to the object/texture size
GLfloat scalex = 1.0;
GLfloat scaley = 1.0;
GLfloat offsetx= 0.0;
GLfloat offsety= 0.0;

//GLdouble gens[4] = {1.0,0.0,0.0,0.0};
//GLdouble gent[4] = {0.0,1.0,0.0,0.0};
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);

glTexGend(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGend(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
//glTexGendv(GL_S,GL_OBJECT_PLANE,gens);
//glTexGendv(GL_T,GL_OBJECT_PLANE,gent);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(scalex,scaley,1.0f);
glTranslatef(offsetx,offsety,0.0);

//do the normal rendering
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
...

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

0 голосов
/ 09 января 2012

gluTesselator не сделает один единственный выпуклый многоугольник из вогнутого многоугольника, потому что это математически невозможно.Он генерирует несколько примитивных групп (GL_POLYGON, GL_TRIANGLE, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN), и это то, что вам нужно передать в OpenGL.Добавьте обратные вызовы тесселатора в glBegin и glEnd.

...