Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: C: Bezier-käyrä (SDL)

KoodiNoppa [18.04.2007 01:02:42]

#

Ohjelma siis piirtää ns. Bezier-käyrän. Tietääkseni tätä ei ole ennen näkynyt vinkeissä, joten nyt olisi aika sille.
Bezier-käyrää käytetään monenlaisissa ohjelmissa kuvankäsittelyohjelmista 3d-työkaluihin (ainakin Blender). Idea on melko yksinkertainen:
http://en.wikipedia.org/wiki/Bézier_curve
Siellä on myös jonkinlaista koodia, mutta ajattelin laittaa sen SDL:lle. Sivulla on animaatioita jotka selventävät mukavasti koodissa olevaa alkukommenttia.

Sanokaa jos jokin on pielessä tai on toivomisen varaa, tämä on ensimmäinen koodivinkkini... Ja muistakaa SDL-linkkeri :)

#include "SDL/SDL.h"

/*
Bezier-kurvi.
Tätä koodia saa käyttää aivan vapaasti jos tarvitsee. Ohjelma laskee käyrän kolmen pisteen
avulla:
1.Aloituspiste
2."taivutuspiste"
3.lopetuspiste.
Niiden väliin voisi kuvitella kaksi suoraa. Kummastakin otetaan jokin kohta, esim. puoliväli.
Niiden pisteiden väliin piirretään viiva, jonka puoliväliin piirretään jälleen piste. Kyseinen
piste on käyrän keskipiste. Kun valitaan tarpeeksi kohtia, esim. 1/1000,2/1000 jne. aina täyteen
1000/1000 asti, saadaan käyrä näkyviin.*/

/*
Käyttöohje.
Jos mitään näppäintä ei ole pohjassa, "taivutuspiste" seuraa hiirtä. Vasen näppäin pohjass alkupiste
seuraa hiirtä. Oikea näppäin ja loppupiste seuraa. Rullasta lisätään ja vähennetään tarkkuutta.
Punainen=alkupiste
Vihreä="taivutuspiste"
Sininen=loppupiste*/

const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
const int SCREEN_BPP = 32;
SDL_Surface *screen = NULL;

int p1x,p2x,p3x,p1y,p2y,p3y,am; //Käyrän pää,"taivutuspiste",toinen pää ja viivan tarkkuus.

SDL_Surface* CLS(SDL_Surface *scr){ //CLS
int ul;
    for(ul=0;ul<800*600;ul++)
    {
         ((unsigned int*)scr->pixels)[ul]=0x000000;
    }
    return scr;
}

void bezier(int xs,int ys,int x,int y,int xe,int ye,int amount) //bezier-funktio
{
     double tempx1,tempy1,tempx2,tempy2,tempx3,tempy3;          //Muutama väliaikainen.
     tempx1=xs;                                                 //Käyrän piirrossa tarvittavan
     tempy1=ys;                                                 //viivan tekoon.
     tempx3=xs;                                                 //Piste mihin piirretään.
     tempy3=ys;
     tempx2=x;                                                  //Viivan toinen pää.
     tempy2=y;
     int xx;
     for (xx=0; xx<amount; xx++)                                //Jaetaan käyrä amount-määrään pisteitä
     {
     ((unsigned int*)screen->pixels)[int(tempx3)+int(tempy3)*800]=0xffffff; //piirretään
     tempx1+=double(x-xs)/amount;                                           //viivan päätä liikutetaan
     tempy1+=double(y-ys)/amount;
     tempx2+=double(xe-x)/amount;                                           //toista päätä liikutetaan
     tempy2+=double(ye-y)/amount;
     tempx3=(tempx1*(amount-xx)+(tempx2*xx))/amount;                        //Piste piirretään viivalle
     tempy3=(tempy1*(amount-xx)+(tempy2*xx))/amount;
     }
}
void cursor(int x, int y, int col) //ei liity kurviin...piirtää bezierissä käytetyt pisteet.
{
     ((unsigned int*)screen->pixels)[x+y*800]=col;
     if(x>0){((unsigned int*)screen->pixels)[x-1+y*800]=col;}
     if(x<799){((unsigned int*)screen->pixels)[x+1+y*800]=col;}
     if(y>0){((unsigned int*)screen->pixels)[x+y*800-800]=col;}
     if(y<599){((unsigned int*)screen->pixels)[x+y*800+800]=col;}
}
int main(int argc, char* args[])
{
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) { return 1; }
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

    int mouse,mx,my,ml,mr,ms;

    p1x=100; p1y=100; //pistetään nyt jotkin aloituskoordinaatit...
    p2x=400; p2y=300;
    p3x=700; p3y=500;
    am=500;           //ja viivan tarkkuus.

    while(1)
    {

    SDL_Event event;
    while (SDL_PollEvent(&event))
    {

          mouse=SDL_GetMouseState(&mx, &my);
      switch (event.type)
      {
      case SDL_KEYDOWN:

        break;
      case SDL_KEYUP:
        // If escape is pressed, return (and thus, quit)
        if (event.key.keysym.sym == SDLK_ESCAPE)
           return 0;
        break;
      case SDL_MOUSEBUTTONDOWN:
        if (event.button.button==SDL_BUTTON_LEFT)
           ml=1;

        if (event.button.button==SDL_BUTTON_RIGHT)
           mr=1;
        if (event.button.button==SDL_BUTTON_WHEELUP){
           ms=1;}
        else if (event.button.button==SDL_BUTTON_WHEELDOWN){
           ms=-1;}
        else{
           ms=0;}

        break;
      case SDL_MOUSEBUTTONUP:
        if (event.button.button==SDL_BUTTON_LEFT)
           ml=0;

        if (event.button.button==SDL_BUTTON_RIGHT)
           mr=0;

        break;

      case SDL_QUIT:
        return(0);
      }
    }
    if (ml==1)                                    //säädöt ohjelman sisällä
    {p1x=mx;p1y=my;}
    else if (mr==1)
    {p3x=mx;p3y=my;}
    else
    {p2x=mx;p2y=my;}
    am+=ms*50;
    ms=0;
    CLS(screen);

    bezier(p1x,p1y,p2x,p2y,p3x,p3y,am);           //funktiokutsut
    cursor(p1x,p1y,0xff0000);
    cursor(p2x,p2y,0x00ff00);
    cursor(p3x,p3y,0x0000ff);
    if (SDL_Flip(screen)==-1){return 1;}
    }
    SDL_Quit();
    return 0;
}

tgunner [18.04.2007 23:14:04]

#

Sanoisinko, että ainakin toteutus on perseestä. Koodi on kauheaa ja pitäisikö tuon olla C:tä? Miksi CLS on SDL_Surface? Kauheasti muuttujia ja niistä iso osa on jopa määritelty jokaiselle funktiolle! Mikset käyttänyt bezier-funktiossa taulukkoja tempeille? Miksi noin monta erinimistä muuttujaa?

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta