OpenGL/Hankalat monikulmiot
Ulkoasu
< OpenGL
OpenGL osaa piirtää vain yksinkertaisia, kuperia monikulmioita. Esimerkiksi 3d-mallia ladatessa saattaa olla tarpeen käsitellä myös monimutkaisempia monikulmioita. GLU-kirjastossa on funktioita, joiden avulla voidaan yksinkertaistaa kuinka monimutkainen monikulmio tahansa kolmioiksi.
Esimerkki
[muokkaa | muokkaa wikitekstiä]Esimerkkiä ei ole vielä testattu, eikä siinä tarkisteta taulukoiden arvoalueita tai joitakin virheitä. Lisäksi olisi hyvä käsitellä combine-operaatio ja pintakuvion koordinaatit.
#include <stdio.h> #include <GL/gl.h> #include <GL/glu.h> /* GLU:n antama piirtotila, jolla seuraavat kolmiot määritellään */ GLenum nykyinen_tila; /* GLU:n tuottamat nurkkapisteet pinotaan pistepuskuriin */ #define PISTEPUSKURIN_KOKO 256 float pistepuskuri[PISTEPUSKURIN_KOKO]; int pistepuskurin_kirjoituspaa = 0; /* nurkkapisteiden määrittelyn päätyttyä niistä muodostetaan * käytetyn piirtotilan mukaisesti kolmioita kolmiopuskuriin */ #define KOLMIOPUSKURIN_KOKO 1024 float kolmiopuskuri[KOLMIOPUSKURIN_KOKO]; int kolmiopuskurin_kirjoituspaa = 0; /* callback-funktiot annetaan GLU:lle, joka kutsuu niitä */ void begin_callback(GLenum piirtotila) { nykyinen_tila = piirtotila; } void vertex_callback(double xyz[]) { pistepuskuri[pistepuskurin_kirjoituspaa ] = xyz[0]; pistepuskuri[pistepuskurin_kirjoituspaa + 1] = xyz[1]; pistepuskuri[pistepuskurin_kirjoituspaa + 2] = xyz[2]; pistepuskurin_kirjoituspaa += 3; } void end_callback(void) { int i; switch (nykyinen_tila) { case GL_TRIANGLES: for (i = 0; i < pistepuskurin_kirjoituspaa; i++) { kolmiopuskuri[kolmiopuskurin_kirjoituspaa] = pistepuskuri[i]; kolmiopuskurin_kirjoituspaa++; } break; case GL_TRIANGLE_STRIP: for (i = 0; i < pistepuskurin_kirjoituspaa - 8; i += 3) { kolmiopuskuri[kolmiopuskurin_kirjoituspaa ] = pistepuskuri[i ]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 1] = pistepuskuri[i + 1]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 2] = pistepuskuri[i + 2]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 3] = pistepuskuri[i + 3]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 4] = pistepuskuri[i + 4]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 5] = pistepuskuri[i + 5]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 6] = pistepuskuri[i + 6]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 7] = pistepuskuri[i + 7]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 8] = pistepuskuri[i + 8]; kolmiopuskurin_kirjoituspaa += 9; } break; case GL_TRIANGLE_FAN: for (i = 3; i < pistepuskurin_kirjoituspaa - 5; i += 3) { kolmiopuskuri[kolmiopuskurin_kirjoituspaa ] = pistepuskuri[0]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 1] = pistepuskuri[1]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 2] = pistepuskuri[2]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 3] = pistepuskuri[i ]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 4] = pistepuskuri[i + 1]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 5] = pistepuskuri[i + 2]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 6] = pistepuskuri[i + 3]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 7] = pistepuskuri[i + 4]; kolmiopuskuri[kolmiopuskurin_kirjoituspaa + 8] = pistepuskuri[i + 5]; kolmiopuskurin_kirjoituspaa += 9; } default: break; } pistepuskurin_kirjoituspaa = 0; } void error_callback(GLenum error_code) { const GLubyte *error_string; error_string = gluErrorString(error_code); } GLdouble v1[] = { 0.0, 0.0, 0.0}; GLdouble v2[] = {-1.0, -1.0, 0.0}; GLdouble v3[] = { 0.0, 1.0, 0.0}; GLdouble v4[] = { 1.0, -1.0, 0.0}; int main(int argc, char* argv[]) { /* luodaan uusi tesselointiolio */ GLUtesselator* tess = gluNewTess(); /* rekisteröidään callback-funktiot GLU:n käytettäväksi */ gluTessCallback(tess, GLU_TESS_VERTEX, (GLvoid (*) ()) &vertex_callback); gluTessCallback(tess, GLU_TESS_BEGIN, (GLvoid (*) ()) &begin_callback); gluTessCallback(tess, GLU_TESS_END, (GLvoid (*) ()) &end_callback); gluTessCallback(tess, GLU_TESS_ERROR, (GLvoid (*) ()) &error_callback); /* tesseloidaan */ gluTessBeginPolygon(tess, NULL); gluTessBeginContour(tess); gluTessVertex(tess, v1, (GLvoid*)v1); gluTessVertex(tess, v2, (GLvoid*)v2); gluTessVertex(tess, v3, (GLvoid*)v3); gluTessVertex(tess, v4, (GLvoid*)v4); gluTessEndContour(tess); gluTessEndPolygon(tess); /* poistetaan tesselointiolio */ gluDeleteTess(tess); /* tulostetaan kolmiot */ int i; for (i = 0; i < kolmiopuskurin_kirjoituspaa; i++) { printf("%f ", kolmiopuskuri[i]); } return 0; }
Huomautuksia
[muokkaa | muokkaa wikitekstiä]- GLU:n tesselointifunktiot taipuvat vaikeahkosti yksinkertaiseen kolmiointiin, sillä ne ovat hyvin yleiskäyttöisiä.
- Usein 3d-mallien monikulmiot muutetaan kolmioiksi Delaunayn kolmioinniksi kutsuttuun muotoon. En tiedä tekeekö GLU niin.