Kirjautuminen

Haku

Tehtävät

Koodit: C++: Sierpinskin kolmiot 3D:nä

Kirjoittaja: dvd

Kirjoitettu: 19.12.2009 – 19.02.2012

Tagit: grafiikka, matematiikka, koodi näytille, vinkki

http://en.wikipedia.org/wiki/Sierpinski_triangle

Algoritmina käytän seuraavaa: Laske nykyisistä verteksistä 4 pienempää tetraedria (jotka muodostavat oikein aseteltuna alkup. tetraedrin) ja toista tämä jokaiselle uudelle tetraedrille. Kun on laskettu tarpeeksi uusia verteksejä, ne tallennetaan listaan.

Hieman tyhmästi tallennan jokaisen verteksin erikseen, tulee paljon piirtämistä. Optimointina voisi jokaisen verteksin tallentaa vain kerran ja sitten indeksoida niitä.

Koodi tarvitsee Windowsissa kirjastot SDL, opengl32 ja glu32.

Binääri: http://kuujoo.kapsi.fi/soodit/gfx/sierpinski3d/

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <cmath>
#include <vector>

/*
Simppeli verteksi luokka, tallentaa sijainnin ja RGB arvon(0-1)
*/
class SVertex
{
    public:
    void setPos(float x_,float y_,float z_)
    {
        x=x_;
        y=y_;
        z=z_;
    }
    void setColor(float r_, float g_, float b_)
    {
        r=r_;
        g=g_;
        b=b_;
    }
    float x,y,z;
    float r,g,b;
};

class CSierpinskiFractal
{
    private:

    /*
    "Objektin" verteksit tallennetaan listaan, josta ne on helppo syöttää, esim. vertex arraylle.
    */
    std::vector<SVertex>vlist;
    public:
    void clean()
    {
        vlist.clear();
    }
    SVertex *getVertex(int id)
    {
        return &vlist.at(id);
    }
    int getVertexCount()
    {
        return vlist.size();
    }
    void sierpinski3D(const SVertex &a, const SVertex &b, const SVertex &c, const SVertex &d, const int depth)
    {
        //mikäli ei olla piirto "syvyydessä"
        if(depth>0)
        {
            //luodaan 7 uutta verteksiä nykyisen "Tetrahedrin" sisälle, verteksit luodaan  särmien puoleen väleihin
            SVertex np[6];
                np[0].setPos((a.x+b.x)/2,(a.y+b.y)/2,(a.z+b.z)/2);
                np[0].setColor((a.r+b.r)/2,(a.g+b.g)/2,(a.b+b.b)/2);
                np[1].setPos((b.x+d.x)/2,(b.y+d.y)/2,(b.z+d.z)/2);
                np[1].setColor((b.r+d.r)/2,(b.g+d.g)/2,(b.b+d.b)/2);
                np[2].setPos((d.x+a.x)/2,(d.y+a.y)/2,(d.z+a.z)/2);
                np[2].setColor((a.r+d.r)/2,(a.g+d.g)/2,(a.b+d.b)/2);
                np[3].setPos((b.x+c.x)/2,(b.y+c.y)/2,(b.z+c.z)/2);
                np[3].setColor((b.r+c.r)/2,(b.g+c.g)/2,(b.b+c.b)/2);
                np[4].setPos((d.x+c.x)/2,(d.y+c.y)/2,(d.z+c.z)/2);
                np[4].setColor((d.r+c.r)/2,(d.g+c.g)/2,(d.b+c.b)/2);
                np[5].setPos((a.x+c.x)/2,(a.y+c.y)/2,(a.z+c.z)/2);
                np[5].setColor((a.r+c.r)/2,(a.g+c.g)/2,(a.b+c.b)/2);
            //kutsutaan rekursiivisesti uusilla arvoilla,
            sierpinski3D(a,np[0],np[5],np[2],depth-1);
            sierpinski3D(b,np[3],np[0],np[1],depth-1);
            sierpinski3D(c,np[5],np[3],np[4],depth-1);
            sierpinski3D(np[2],np[1],np[4],d,depth-1);
        }
        //mikäli ollaan piirtosyvyydessä...
        else
        {
            //asetetaan verteksit verteksilistaan.
            vlist.push_back(a);
            vlist.push_back(b);
            vlist.push_back(d);
            vlist.push_back(b);
            vlist.push_back(c);
            vlist.push_back(d);
            vlist.push_back(c);
            vlist.push_back(a);
            vlist.push_back(d);

        }
    }
};

int main(int argc, char *argv[])
{
    SDL_Surface *screen = SDL_SetVideoMode(600, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF|SDL_OPENGL);
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    glViewport(0, 0, 600, 600);
    glMatrixMode(GL_PROJECTION);
    gluPerspective(45, 600.0/600.0, 1, 100);
    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);

    //alku vertexeillä määritetään koko systeemin koko
    SVertex vertices[4];
        vertices[0].setColor(1,0,0);
        vertices[1].setColor(0,1,0);
        vertices[2].setColor(0,0,1);
        vertices[3].setColor(1,1,1);
        vertices[0].setPos(-5,-5,3);
        vertices[1].setPos(5,-5,3);
        vertices[2].setPos(0,-5,-5);
        vertices[3].setPos(0,5,0);
    CSierpinskiFractal frak;

    //syötetään lähtöarvot, ja "syvyys", fraktaalille. fraktaali laskee listaan verteksien paikat.
    frak.sierpinski3D(vertices[0],vertices[1],vertices[2],vertices[3],6);
    SDL_Event event;
    bool    isRunning   =   true;
    while(isRunning)
    {
        SDL_PollEvent(&event);
        if ( event.type == SDL_QUIT )
        {
            isRunning = false;
        }

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        glTranslatef(0,0,-20);

        //pyöritetään
        glRotatef(0.5*SDL_GetTicks()/10,0,1,0);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
            //osoitin ensimmäisen verteksin x pisteeseen
            glVertexPointer(3, GL_FLOAT, sizeof(SVertex),&frak.getVertex(0)->x);
            //osoitin ensimmäisen verteksin punaiseen väriarvoon
            glColorPointer(3,GL_FLOAT,   sizeof(SVertex),&frak.getVertex(0)->r);
                glDrawArrays(GL_TRIANGLES,0 , frak.getVertexCount());
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
        SDL_GL_SwapBuffers();
    }
    SDL_FreeSurface(screen);
    SDL_Quit();
    return 0;
}

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta