Kurs FORTRANU | ||
---|---|---|
Předcházející |
Žádný počítačový jazyk si nemůže z důvodů přenositelnosti dovolit přímo do své definice zahrnout grafické operace, které jsou silne závyslé od HW a navíc dochází v této oblasti k masivnímu rozvoji technologií a žádné všeobecně uznávané grafické rozhraní neexistuje. Proto pokud nějaký program chce používat operace s grafikou musí použít nějakou grafickou knihovnu. Z hlediska programování je to jakakoli knihovna a proto s implementací nebývají žádné problémy. Ukážeme použití nejrozšířenejší nízkoůrovňové knihovny OpenGL ve fortranu. Není to ovšm jediná použitelná knihovna.
Nejsofistikovanější fortranovskou knihovnou je PgPlot [http://www.astro.caltech.edu/~tjp/pgplot/] od Tima Pearsona která umí všechny možné grafické operace včetne zobrazování obrázků, kreslení grafů a podobně. Všetně rozsáhlého manuálu je volně k dispozici.
Knihovna DISLIN [http://www.linmpi.mpg.de/dislin/] je o poznání jednodužší ale zase se může hodit pro jednoduché projekty. Volně k dispozici je ovšem jen verze pro f90.
Obě uvedené knihovny jsou určené spíše pro neinteraktivní práci, vykreslují ale neumožňují modifikovat data a podobně. Naproti tomu OpenGL je nízkourovňová knihovna umožňující programovat jakékoli grafické aplikace bez omezení. Existují porty pro všechny možné jazyky. OpenGL i ostatní grafické knihovny pracuje na poněkud jiném principu, než jsme při obyčejném programování zvykli. Obyčejně všechny programy vykonávají příkazy od začátku do konce a pak skončí, maximálně se občas uživatele na něco zeptají. Ovšem tenhle model ovládání programů je zcela nepoužitelný v případě, ze máme aplikaci s menu a podobně, kde je běh programu různě měněn v závislosti například na uživatelově rozhodnutí.
Proto OpenGL pracuje jinak. Při startu se nejprve vytvoří procedury, které obhospodařují jednotlivé akce uživatele případě dalších zařízení. Na začátku se též obyčejně vykreslí do paměti grafické karty obrázek a pokud chce uživatel například myší otáčet obrázek pak jen grafická karta přepočítává základní objekt tak ja by jej viděl uživatel a data pak posílá na obrazovku. Program pak je vlastně sada příkazů pro HW procesor.
Ukázka, kterou uvedeme bude vykreslovat torus (pneumatiku) podle toho v jaké poloze je zrovna ukazatel myši na obrazovce. Dále bude ukazovat jeho souřadnice. Levé tlačítko myši ukáže jednduché, menu například umožňující ukončit program. Zajímavé je experimentovat s polohou a barvou světelných zdrojů které torus osvětlují.
! vzorova implmentace GL+GLUT Module callback use opengl_gl use opengl_glu use opengl_glut implicit none real :: px,py contains subroutine init use opengl_gl use opengl_glu use opengl_glut character(len=20) :: out = "ahoj svete" integer(glint) :: i,image_data(3*40*40) contains subroutine init use opengl_gl use opengl_glu use opengl_glut character(len=20) :: out = "ahoj svete" integer(glint) :: i,image_data(3*40*40) call glclearcolor(0.0, 0.0, 1.0, 1.0) call glmatrixmode(GL_PROJECTION) call glloadidentity() call gltranslatef(-0.1,0.1,0.0) call glrotatef(30.0,0.0,0.0,10.0) call glnewlist(1,GL_COMPILE) call glutsolidtorus(0.275_gldouble,0.45_gldouble,50,55) call glendlist call glLightfv(GL_LIGHT0, GL_DIFFUSE, (/1.0, 1.0, 0.0, 0.0 /)) call glLightfv(GL_LIGHT0, GL_POSITION, (/0.0, 0.0, 10.0, 10.0 /) ) call glEnable(GL_LIGHT0) call glEnable(GL_LIGHTING) call glMaterialfv(GL_FRONT, GL_AMBIENT, (/0.4, 0.4, 0.4, 0.0/)) end subroutine init subroutine display use opengl_gl use opengl_glu use opengl_glut integer :: i character(len=80) :: data call glclear(GL_COLOR_BUFFER_BIT) write(data,*) px,py call glrasterpos2f(-0.1,0.95) do i = 1, len_trim(data) call glutbitmapcharacter(GLUT_BITMAP_TIMES_ROMAN_24,ichar(data(i:i))) enddo call glrotatef(px/100.0,00.0,10.0,0.0) call glcalllist(1) call glutswapbuffers call glflush end subroutine display subroutine mouse(x,y) integer(kind=glcint) , intent(in out) :: x,y integer :: i write(*,*) x,y px = x+200!abs(x-150.0)+10.0 py = y+200!abs(y-150.0)+10.0 call display end subroutine mouse subroutine mainmenu(value) integer, intent(inout) :: value !write(*,*) "value = ",value if( value == 1 ) then write(*,*) "help" endif if( value == 666 ) stop end subroutine mainmenu end Module callback program zk1 use opengl_gl use opengl_glu use opengl_glut use callback integer(kind=glcint) :: iwin, imenu integer(kind=glenum) :: itemp call glutinit() call glutinitdisplaymode(GLUT_DOUBLE + GLUT_RGB) iwin = glutcreatewindow("zk1") ! menu imenu = glutcreatemenu(mainmenu) call glutaddmenuentry("Help",1) call glutaddmenuentry("Quit",666) call glutattachmenu(GLUT_RIGHT_BUTTON) call init call glutmotionfunc(mouse) call glutdisplayfunc(display) call glutmainloop() end program zk1
Jak to celé funguje? Nejprve je třeba knihovnu i window system initializovat. To lze demonstrovat na jednoduchem programu:
Program InitGL use opengl_gl use opengl_glu use opengl_glut integer(kind=glcint) :: iwin, imenu integer(kind=glenum) :: itemp call glutinit() call glutinitdisplaymode(GLUT_RGB) iwin = glutcreatewindow("initgl") call glutmainloop() end program initgl
Tento program zinitializuje knihovnu v RGB modu a vytvoří prázdné okno se jménem initgl a spusti hlavní tzv. zpracovávač událostí. Ten je, zhruba řečeno, představován nekonečným cyklem ve kterém se testují stavy jednotlivých zařízení (klavesnice, myš) a v případě, že se například uživatel zmáčne klávesu tak vyvolá asociovanou funkci (viz dále). V tomto případě ovšem žádné nejsou a tak program nebude reagovat na nic a bude třeba jej nasilím sejmout.
Ovládání je realizováno pomocí tzv. callbacků což jsou funkce, které můžeme svázat s nejakou uživatelovou akcí. Přiřazení funkcí se děje pomocí glutmotionfunc(), glutdisplayfunc() funkcí které zaregistrují danou funci jako callback. Můžeme tak ošetřit jednotlivé akce uživatele. Například v subroutinw mouse kterým gl předává jako parametry polohu ukazatele myši v aktualním okně vypisujeme tyto souřadnice na stadradni vystup. Na základě těchto souřadnic pak můžeme otáčet s objektem.
Vlastní nadefinování a vytvoření objektu je v proceduře init, kde se v paměti GL vyrobí objekt a projekce ze které se uživatel dívá. Dále pak poloha světelného zdroje na osvětlení scény.
Většina počítačů ma nějakou podporu GL v sobě, většinou je to knihovna messa která umožňuje fungovat jako GL knihovna i na strojích kde GL neni k dispozici, dochází ovšem k podstatnému zpomalení. Fortran interface lze stahout z [http://math.nist.gov/f90gl/], kde jsou zdrojáky které po přeložení vytvoří jak fortranovsky interface tak moduly s daty tak aby šlo normálně používat OpenGL v F90. Nakonec uvádíme Makefile potřebný pro přeložení ukázkových programů.
OGLLIBDIR = -L$(HOME)/f90gl/lib #-L/usr/lib # the directory containing the X11 libraries X11LIBDIR = -L/usr/X11R6/lib/ # the fortran 90 libraries for OpenGL, including GLUT, GLU and OpenGL F90GLUTLIB = -lf90glut -lf90GLU -lf90GL -lglut -lGLU -lGL # the X11 libraries X11LIB = -lXt -lXmu -lXi -lXext -lX11 -lm # the f90 compiler flag for specifying the location of MOD files MODS = $(HOME)/f90gl/include/GL # fortran 90 compiler and compiler flags F90 = ifc F90FLAGS = # fortran 90 compiler flag for fixed source form FFIXED = -FI #----------- end of user configuration parameters ------------ all: glkinds.o interf.o intrfglt.o intrfglu.o fwrapglt.o fwrap.o fwrapglu.o \ zk zk1 zk: zk.f90 $(F90) $(F90FLAGS) -o zk zk.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) zk1: zk1.f90 $(F90) $(F90FLAGS) -o zk1 zk1.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) fwrapglt.o: $(F90) $(F90FLAGS) -c $(MODS)/fwrapglt.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) fwrap.o: $(F90) $(F90FLAGS) -c $(MODS)/fwrap.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) fwrapglu.o: $(F90) $(F90FLAGS) -c $(MODS)/fwrapglu.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) glkinds.o: $(F90) $(F90FLAGS) -c $(MODS)/glkinds.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) interf.o: $(F90) $(F90FLAGS) -c $(MODS)/interf.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) intrfglt.o: $(F90) $(F90FLAGS) -c $(MODS)/intrfglt.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) intrfglu.o: $(F90) $(F90FLAGS) -c $(MODS)/intrfglu.f90 \ $(OGLLIBDIR) $(F90GLUTLIB) $(X11LIBDIR) $(X11LIB) clean: rm -f *.o *.d work.pc*
Předcházející | Domů | |
Rozsáhlé projekty: CVS,make,knihovny |