// (c) Dinko Korunic, 36355514, kreator@fly.srk.fer.hr // Zadatak broj 7 iz predmeta Racunalna grafika #include #include #include #include #include #define MAXX 640 // max x #define MAXY 480 // max y #define LPOB 8 // modifikator #define DINT 0 // zbraja intenzitetu #define MINT 1 // mnozi intenzitet class MyDisplay { // klasa MyDisplay u kojoj se nalaze inicijalizacijske xlib // rutine, kao i postavljanje background i foreground boje, itd. XGCValues gcv; unsigned long wp, bp; int winx, winy; public: Display *disp; Window win; GC gc; XEvent ev; void MyWait(void); int winsx, winsy, screen; MyDisplay(int _winx, int _winy, int _winsx, int _winsy); ~MyDisplay(); }; MyDisplay::MyDisplay(int _winx=0, int _winy=0, int _winsx=MAXX, int _winsy=MAXY) : winx(_winx), winy(_winy), winsx(_winsx), winsy(_winsy) { // konstruktor koji sluzi za misc. inicijalizaciju cout << "Initialising graphic subsystem.." << endl; // otvaranje displaya if ((disp=XOpenDisplay(NULL))==NULL) { cerr << "I can't open display." << endl; exit(EXIT_FAILURE); } screen=DefaultScreen(disp); // stvaranje prototipnog prozora win=XCreateSimpleWindow(disp, DefaultRootWindow(disp), winx, winy, winsx, winsy, 1, wp=WhitePixel(disp, screen), bp=BlackPixel(disp, screen)); XSelectInput(disp, win, StructureNotifyMask | KeyPressMask | ExposureMask); // mapiranje prozora XMapWindow(disp, win); while(1) { // cekaj dok nije gotovo XNextEvent(disp, &ev); if (ev.type==MapNotify) break; } gcv.foreground=wp; gcv.background=bp; // stvori gc gc=XCreateGC(disp, win, GCForeground | GCBackground, &gcv); cout << "done." << endl; } MyDisplay::~MyDisplay() { // destruktor za graficki engine cout << "Shutting graphic subsystem.." << endl; XFreeGC(disp, gc); XDestroyWindow(disp, win); XCloseDisplay(disp); cout << "done." << endl; } void MyDisplay::MyWait(void) { // postavi wait na keypress XSelectInput(disp, win, KeyPressMask | ExposureMask); while(1) { XNextEvent(disp, &ev); if (ev.type==KeyPress) break; } } // vrh poligona struct Vrh { int x, y, z; // koordinate u sustavu scene double xo, yo, zo; // koordinate u sustavu oka int xp, yp, // koordinate prikaza intenzitet; // intenzitet u vrhu double vx, vy, vz; // komponente vektora koji izvire iz vrha }; // struktura u koju se ucitavaju vrhovi tijela struct Matrica { int t, // broj vrhova po katu k, // broj katova boja; Vrh **Mat; // matrica od k redaka i t stupaca }; // poligon struct Poligon { int n, // broj vrhova poligona boja, // boja 0-crvena 1-zelena 2-plava 3-siva vidljivost; float A, B, C, D; // koeficijenti ranvine u kojoj lezi poligon Vrh **Polje; // polje vrhova poligona orijentirano u smjeru // kazaljke na satu }; class MiscDraw : public MyDisplay { Colormap cmap; XColor xcolor, colorcell; int darkcolor, lightcolor, black, white; public: XImage *image; long translate[4]; /* for converting colors */ MiscDraw(); }; MiscDraw::MiscDraw() { cmap=DefaultColormap(disp, screen); if (XAllocNamedColor(disp, cmap, "red", &colorcell, &xcolor)) translate[0]=colorcell.pixel; if (XAllocNamedColor(disp, cmap, "green", &colorcell, &xcolor)) translate[1]=colorcell.pixel; if (XAllocNamedColor(disp, cmap, "blue", &colorcell, &xcolor)) translate[2]=colorcell.pixel; if (XAllocNamedColor(disp, cmap, "grey", &colorcell, &xcolor)) translate[3]=colorcell.pixel; image=XGetImage(disp, win, 0, 0, MAXX, MAXY, AllPlanes, ZPixmap); } class MyDraw7 : public MiscDraw { Matrica MyMatrica; // za smjestaj vrhova Poligon *PoljePoligona; // polje ciji elementi su strukture koje // sadrzavaju poligone int *Lx, *Lintenzitet, *Dx, *Dintenzitet, BrojPoligona; // sadrzi broj poligona od kojih je // sastavljeno tijelo Vrh Ociste, Glediste, Izvor; void Input(Matrica *); void DajIntenzitet(Vrh *); void OdrediVidljivost(Poligon *); void PridodajVrh(Poligon *); void Alociraj(void); void PopuniSpremnike(Poligon *); void IzracunajRavninu(Poligon *); void Topologija(Matrica *, Poligon *); void TransformirajPogled(Vrh *); void Projekcija(Vrh *); void PridodajVrhovima(Poligon *); public: MyDraw7(); }; MyDraw7::MyDraw7() { Input(&MyMatrica); PoljePoligona=new Poligon[BrojPoligona=2+MyMatrica.t*(MyMatrica.k-1)]; // popunjavamo polje poligona sa svim potrebnim poligonima Topologija(&MyMatrica, PoljePoligona); int i, j; // idemo po svim vrhovima i radimo transformacije for (i=0; ixp, PoljePoligona[i].Polje[j]->yp, PoljePoligona[i].Polje[(j+1)%PoljePoligona[i].n]->xp, PoljePoligona[i].Polje[(j+1)%PoljePoligona[i].n]->yp); XDrawString(disp, win, gc, 10, 10, "RGF labos br. 7 - wireframe", 27); XFlush(disp); MyWait(); XClearWindow(disp, win); // crtamo hidden line wireframe for (i=0; ixp, PoljePoligona[i].Polje[j]->yp, PoljePoligona[i].Polje[(j+1)%PoljePoligona[i].n]->xp, PoljePoligona[i].Polje[(j+1)%PoljePoligona[i].n]->yp); XDrawString(disp, win, gc, 10, 10, "RGF labos br. 7 - wireframe2", 28); XFlush(disp); MyWait(); XClearWindow(disp, win); // crtamo osjencane poligone Alociraj(); int k, intenzitet; double derintenzitet; for (i=0; i> M->k; cin >> M->t; cin >> M->boja; M->Mat=new (Vrh *)[M->k]; int i; for (i=0; ik; ++i) M->Mat[i]=new Vrh[M->t]; int j; for (i=0; ik; ++i) for (j=0; jt; ++j) { cin >> M->Mat[i][j].x; cin >> M->Mat[i][j].y; cin >> M->Mat[i][j].z; M->Mat[i][j].vx=M->Mat[i][j].vy=M->Mat[i][j].vz=0; } cout << "Unesi koordinate ocista (x, y, z):" << endl; cin >> Ociste.x; cin >> Ociste.y; cin >> Ociste.z; cout << "Unesi koordinate gledista (x, y, z):" << endl; cin >> Glediste.x; cin >> Glediste.y; cin >> Glediste.z; cout << "Unesi koordinate izvora svjetlosti (x, y, z):" << endl; cin >> Izvor.x; cin >> Izvor.y; cin >> Izvor.z; } void MyDraw7::DajIntenzitet(Vrh *V) { // racunamo vektor iz vrha prema izvoru double ax=Ociste.x-V->x, ay=Ociste.y-V->y, az=Ociste.z-V->z; // racunamo kut koji zatvaraju taj vektor i vektor iz vrha nastao // kao prosjecni vektor normala ploha koje se sjeku u tom vrhu double coskut=(V->vx*ax+V->vy*ay+V->vz*az)/ sqrt(ax*ax+ay*ay+az*az)/ sqrt(V->vx*V->vx+V->vy*V->vy+V->vz*V->vz); if (coskut<0) coskut=-0.25; V->intenzitet=10+53*coskut; if (V->intenzitet<10) V->intenzitet=10; } void MyDraw7::OdrediVidljivost(Poligon *Ulaz) { double xsred=0, ysred=0, zsred=0; int i; for (i=0; in; ++i) // odredjujemo koordinate sredine poligona { xsred+=Ulaz->Polje[i]->x; // radimo u sustavu scene ysred+=Ulaz->Polje[i]->y; zsred+=Ulaz->Polje[i]->z; } xsred/=i; // odredili smo ih (u i=ulaz->n) ysred/=i; zsred/=i; double ax=Ociste.x-xsred, // odredili smo vektor s hvatistem u ay=Ociste.y-ysred, // sredini poligona az=Ociste.z-zsred; // i vrhom u ocistu // kut -> ustvari vrijednost kosinusa double kut=acos((ax*Ulaz->A+ay*Ulaz->B+az*Ulaz->C) /sqrt(ax*ax+ay*ay+az*az) /sqrt((Ulaz->A*Ulaz->A)+(Ulaz->B*Ulaz->B)+(Ulaz->C*Ulaz->C))); if (kutvidljivost=0; else Ulaz->vidljivost=1; } void MyDraw7::PridodajVrhovima(Poligon *P) { // odredjujemo normirane vrijednosti vektora double aps=sqrt(P->A*P->A+P->B*P->B+P->C*P->C), xnorm=P->A/aps, ynorm=P->B/aps, znorm=P->C/aps; for (int i=0; in; ++i) // idemo po svim vrhovima poligona { P->Polje[i]->vx+=xnorm; // i pridodajemo im vrijednosti P->Polje[i]->vy+=ynorm; // normiranog vektora P->Polje[i]->vz+=znorm; } } void MyDraw7::Alociraj(void) { Lx=new int[MAXY]; Dx=new int[MAXY]; Lintenzitet=new int[MAXY]; Dintenzitet=new int[MAXY]; } void MyDraw7::PopuniSpremnike(Poligon *P) { int i, *adrx, *adrintenzitet, xi, xf, mi, mf, ybrojac, xodluka, yodluka; // inicijalno je sve nula for (i=0; in; i++) { //odredjujemo u koji se spremnik spremaju vrijednosti if (P->Polje[i]->yp>P->Polje[(i+1)%P->n]->yp) { adrx=Dx; adrintenzitet=Dintenzitet; yodluka=-1; } else { adrx=Lx; adrintenzitet=Lintenzitet; yodluka=1; } //radimo DDA postupak za x spremnike if (P->Polje[i]->xpPolje[(i+1)%P->n]->xp) xodluka=1; else xodluka=-1; xi=P->Polje[i]->xp; xf=-abs(P->Polje[(i+1)%P->n]->yp-P->Polje[i]->yp); if (xf) { mi=abs((P->Polje[(i+1)%P->n]->xp-P->Polje[i]->xp) /(P->Polje[(i+1)%P->n]->yp-P->Polje[i]->yp)); mf=abs(2*((P->Polje[(i+1)%P->n]->xp-P->Polje[i]->xp) %(P->Polje[(i+1)%P->n]->yp-P->Polje[i]->yp))); for (ybrojac=P->Polje[i]->yp; yodluka*ybrojac<=yodluka*(P->Polje[(i+1)%P->n]->yp); ybrojac+=yodluka) { if (ybrojac>=0 && ybrojac=0) { xi+=xodluka; xf-=2*abs(P->Polje[(i+1)%P->n]->yp -P->Polje[i]->yp); } } } else { if (P->Polje[i]->xp>P->Polje[(i+1)%P->n]->xp) Dx[P->Polje[i]->yp]=xi; else Lx[P->Polje[i]->yp]=xi; } // radimo DDA postupak za intenzitet meŠu pojedinim linijama // xodluka ima ulogu intenzitetodluka if (P->Polje[i]->intenzitetPolje[(i+1)%P->n]->intenzitet) xodluka=1; else xodluka=-1; xi=P->Polje[i]->intenzitet; xf=-abs(P->Polje[(i+1)%P->n]->yp-P->Polje[i]->yp); if (xf) { mi=abs((P->Polje[(i+1)%P->n]->intenzitet -P->Polje[i]->intenzitet)/ (P->Polje[(i+1)%P->n]->yp-P->Polje[i]->yp)); mf=abs(2*((P->Polje[(i+1)%P->n]->intenzitet -P->Polje[i]->intenzitet)% (P->Polje[(i+1)%P->n]->yp-P->Polje[i]->yp))); for (ybrojac=P->Polje[i]->yp; yodluka*ybrojac<=yodluka*(P->Polje[(i+1)%P->n]->yp); ybrojac+=yodluka) { if (ybrojac>=0 && ybrojac=0) { xi+=xodluka; xf-=2*abs(P->Polje[(i+1) %P->n]->yp-P->Polje[i]->yp); } } } else { if (P->Polje[i]->xp>P->Polje[(i+1)%P->n]->xp) Dintenzitet[P->Polje[i]->yp]=xi; else Lintenzitet[P->Polje[i]->yp]=xi; } } } void MyDraw7::IzracunajRavninu(Poligon *P) { P->A=(P->Polje[1]->y - P->Polje[0]->y) *(P->Polje[2]->z - P->Polje[0]->z) -(P->Polje[1]->z - P->Polje[0]->z) *(P->Polje[2]->y - P->Polje[0]->y); P->B=-(P->Polje[1]->x - P->Polje[0]->x) *(P->Polje[2]->z - P->Polje[0]->z) +(P->Polje[1]->z - P->Polje[0]->z) *(P->Polje[2]->x - P->Polje[0]->x); P->C=(P->Polje[1]->x - P->Polje[0]->x) *(P->Polje[2]->y - P->Polje[0]->y) -(P->Polje[1]->y - P->Polje[0]->y) *(P->Polje[2]->x - P->Polje[0]->x); P->D=-(P->Polje[0]->x * P->A)-(P->Polje[0]->y * P->B) -(P->Polje[0]->z * P->C); } void MyDraw7::Topologija(Matrica *M, Poligon *P) { int n=0; // ovo tu stvara prvi poligon - bazu na najgornjem katu P[n].Polje=new (Vrh *)[M->t]; P[n].n=M->t; P[n].boja=M->boja; int i; for (i=0; it; ++i) P[n].Polje[i]=&M->Mat[0][i]; // stvaranje popisa vrhova za poligone plasta koliko ima katova // poligona plasta int j; for (i=0; ik-1; ++i) { // poligona po katu ima onoliko koliko je tocaka zadano po // istom for (j=0; jt; ++j) { P[++n].n=4; P[n].boja=M->boja; P[n].Polje=new (Vrh *)[4]; P[n].Polje[0]=&M->Mat[i][j]; P[n].Polje[1]=&M->Mat[i+1][j]; P[n].Polje[2]=&M->Mat[i+1][(j+1)%M->t]; P[n].Polje[3]=&M->Mat[i][(j+1)%M->t]; } } //stvara drugu bazu - donju P[++n].Polje=new (Vrh *)[M->t]; P[n].n=M->t; P[n].boja=M->boja; for (i=0; it; ++i) P[n].Polje[i]=&M->Mat[M->k-1][M->t-1-i]; } void MyDraw7::TransformirajPogled(Vrh *V) { double xg1=Glediste.x-Ociste.x, yg1=Glediste.y-Ociste.y, zg1=Glediste.z-Ociste.z, xg2=sqrt(xg1*xg1+yg1*yg1), sina=yg1/xg2, cosa=xg1/xg2, sinb=xg2/sqrt(xg1*xg1+yg1*yg1+zg1*zg1), cosb=zg1/sqrt(xg1*xg1+yg1*yg1+zg1*zg1); V->xo=V->x*sina-V->y*cosa-Ociste.x*sina+Ociste.y*cosa; V->yo=-V->x*cosa*cosb-V->y*sina*cosb+V->z*sinb+Ociste.x*cosa*cosb +Ociste.y*sina*cosb-Ociste.z*sinb; V->zo=V->x*cosa*sinb+V->y*sina*sinb+V->z*cosb- Ociste.x*cosa*sinb-Ociste.y*sina*sinb-Ociste.z*cosb; Glediste.xo=Glediste.yo=0; Glediste.zo=sqrt(xg1*xg1+yg1*yg1+zg1*zg1); } void MyDraw7::Projekcija(Vrh *V) { V->xp=V->xo/V->zo*Glediste.zo; V->yp=V->yo/V->zo*Glediste.zo; } int main(void) { MyDraw7 MyOb; return EXIT_SUCCESS; }