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.