2D grafikus rendszerek Szirmay-Kalos László
2D grafikus rendszerek (funkcionális modell) TV-1 TM-1 Bemeneti csővezeték Eszköz- képtér Képtér- világ Világ- lokális mod. Eszköz koord. (xe, ye) Kép frissités kamera Virtuális világ Kurzor (xp, yp) Pixel műveletek Raszteri- záció Vágás Világ- képtér Modellezési transzf. rasztertár Kimeneti csővezeték TV TM
2D grafikus editor: GUI, use-case, dinamikus modell LD L LU L R MouseLDown első pont MouseLDown második ... MouseLDown n. MouseRDown utolsó MouseLDown pick? MouseMove mozgat MouseLUp letesz
Osztálydiagram Scene actobj actprim InputPipe() Pick() Render() Window state MouseLD() MouseLU() MouseMov() PutPixel() Object transform AddPrimitive() GetPrimitive() VirtualWorld AddObject() GetObject() RenderPrimitive Transform() Clip() Draw() Primitive color AddPoint() Vectorize() Point x,y Camera ClipWindow() ViewTransform() Polyline Vectorize() Curve Interpolate() Vectorize() Polygon Vectorize() LineList Clip() Draw() Polygon Clip() Draw() PointList Clip() Draw() Bezier Interpolate() B-Spline Interpolate()
Kimeneti csővezeték: Render Scene :: Render ( ) { Transform Tv = camera.ViewTransform( ); for each object obj { // prioritás Transform Tm = obj -> Transform( ); Transform Tc = Tm * Tv; for each primitive p of object obj { // prioritás RenderPrimitive * rp = p -> Vectorize( ); rp -> Transform( Tc ); if ( rp -> Clip( camera.ClipWindow ) ) rp -> Draw( ); }
Vektorizáció class Curve : Primitive { virtual Point Interpolate( double tt ) = 0; RenderPrimitive Vectorize( ) { LineList linelist = new LineList(); for(int i = 0; i <= NVECTOR; i++) { double t = (double)i / NVECTOR; linelist -> AddPoint( Interpolate( t ) ); } return linelist; };
Bezier görbe interpoláció ( ) n class Bezier : Curve { Point Interpolate( double tt ) { Point rr(0, 0); for(int i = 0; i < npoints; i++) { double Bi = 1.0; for(int j = 1; j <= i; j++) Bi *= tt * (npoints-j)/j; for( ; j < npoints; j++) Bi *= (1-tt); rr += points[i] * Bi; } return rr; }; Bi(t) = t i (1-t)n-i i r(t) = S Bi(t) ri
RenderPrimitive class RenderPrimitive { Point * points; Color color; void Transform( Transform T ) { for each point i do points[i].Transform( T ); } virtual Bool Clip( Rect cliprect ) = 0; virtual void Draw( ) = 0; }; class Line : public RenderPrimitive { Line( Point p1, Point p2 ) { points = new Point[2]; points[0] = p1; points[1] = p2; Bool Clip( Rect cliprect ) { Cohen-Sutherland vágás } void Draw( ) { Szakaszrajzoló algoritmus: PutPixel(X, Y, color) }
Bemeneti csővezeték: pontok beépítése a virtuális világba Scene :: InputPipeline( X, Y ) { Object * obj = world.Object( actobject ); Transform Tm = obj -> Transform( ); Transform Tv = camera.ViewTransform( ); Transfrom Tci = (Tm * Tv).Invert( ); Point p = Point(X, Y).Transform( Tci ); world.Object( actobject ) -> Primitive( actprim ) -> AddPoint(p); } Window :: MouseLDown( X, Y ) { ... ha az állapot szerint a pontot be kell építeni scene.InputPipeline( X, Y ); ....
Primitív (objektum) kiválasztása Scene :: Pick( X, Y ) { Rect pickw( X-5, Y-5, X+5, Y+5 ); fordown each object obj { // vissza prioritás Transform Tm = obj -> Transform( ); Transform Tv = camera.ViewTransform( ); Transform Tc = Tm * Tv; fordown each primitive p of object obj { RenderPrimitive * rp = p -> Vectorize( ); rp -> Transform( Tc ); if ( rp -> Clip( pickw ) ) { actobj = obj; actprim = p; return actobj; } } Window :: MouseLDown( X, Y ) { ... ha az állapot szerint kiválasztás: scene.Pick( X, Y );
Input/Output kezelés init. callback regisztráció main Operating system Windows main GLUT DisplayFunc KeyboadFunc SpecialFunc callback-ek Reshape MousePress OpenGL grafikus hardver MouseMotion IdleFunc applikáció
GLUT-OpenGL OpenGL: GLUT kimeneti csővezeték tesszelláció (GLU), transzformáció, vágás, pick! raszterizáció GLUT Op. Rendszer, Ablakozó rendszer illesztés ablak létrehozás bemeneti események elkapása
OpenGL szintaxis glVertex3dv( … ) gl könyvtár része Paraméterszám 2 - (x, y) 3 - (x, y, z), (R, G, B) 4 - (x, y, z, h) (R, G, B, A) Adattípus b - byte ub - unsigned byte s - short i - int f - float d - double Vektor vagy skalár v - vektor - skalár
Ablakozó – OpenGL – alkalmazás elhelyezkedése applikáció glX, wgl GLUT gl glu X v. MS-Win hw Ablak-kezelés widgetek Ablakozó- gl híd Window menedzsment Utility-k, tesszellátorok
OpenGL: GLUT inicializálás #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> // download!!! main( int argc, char *argv[] ) { glutInitWindowSize(200, 200); glutInitWindowPosition(100, 100); glutInit(&argc, argv); glutInitDisplayMode( GLUT_RGB ); glutCreateWindow("Sample Window"); // callback függvények glutKeyboardFunc( Keyboard ); glutDisplayFunc( ReDraw ); // transzformáció glViewport(0, 0, 200, 200); glMatrixMode(GL_MODELVIEW); glLoadIdentity( ); glMatrixMode(GL_PROJECTION); gluOrtho2D(0., 100., 0., 100.); // fő hurok glutMainLoop(); } OpenGL: GLUT inicializálás KeyPress WM_KEYDOWN Expose WM_PAINT (200,200) window (100,100) viewport (0,0) (0,0)
Eseménykezelés és rajzolás void ReDraw( ) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); } void Keyboard(unsigned char key, int x, int y) { if (key == ‘d’) { glColor3d( 0.0, 1.0, 0.0 ); glBegin(GL_TRIANGLES); glVertex2d(10.0, 10.0); glVertex2d(20.0, 100.0); glVertex2d(90.0, 30.0); glEnd( ); glFlush( ); window (100,100) (0,0) viewport (200,200) (0,0)
2D grafikus editor L L L R MouseLDown első pont MouseLDown második ... MouseLDown n. MouseRDown utolsó
Glut/OpenGL program architektúra Operating system Windows GLUT main Redraw MousePress transzform vágás MouseMotion Color buffer: RGB raszterizáció Raszter műveletek API
Osztálydiagram Scene actobj actprim InputPipe() Pick() Render() Window state MouseLD() MouseLU() MouseMov() PutPixel() Object transform AddPrimitive() GetPrimitive() VirtualWorld AddObject() GetObject() RenderPrimitive Transform() Clip() Draw() Primitive color AddPoint() Vectorize() Point x,y Camera ClipWindow() ViewTransform() window viewport Polyline Vectorize() Curve Interpolate() Vectorize() Polygon Vectorize() LineList Clip() Draw() Polygon Clip() Draw() PointList Clip() Draw() Bezier Interpolate() B-Spline Interpolate()
GLUT: inicializálás main(argc, argv) { glutInitWindowSize(200, 200); glutInitWindowPosition(100, 100); glutInit(&argc, argv); glutInitDisplayMode( GLUT_RGB ); glutCreateWindow("2D graphics editor"); glutMouseFunc(MousePress); // callback glutMotionFunc(MouseMotion); glutDisplayFunc(ReDraw); glutMainLoop(); // fő hurok }
GLUT: eseménykezelés void ReDraw( ) { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); window.scene.Render( ); } void MousePress( int button, int state, int x, int y ) { if (button == GLUT_LEFT && state == GLUT_DOWN) window.MouseLD(x, y); … void MouseMotion( int x, int y ) { window.MouseMov(x, y);
OpenGL Render Scene :: Render ( ) { glViewport(camera.viewport.Left(), camera.viewport.Bottom(), camera.viewport.Width(), camera.window.Height()); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D(camera.window.Left(), camera.window.Right(), camera.window.Bottom(), camera.window.Top()); glMatrixMode( GL_MODELVIEW ); for each object obj { glMulMatrix( obj -> Transform( ) ); // 4x4 matrix for each primitive p of object obj { RenderPrimitive * rp = p -> Vectorize( ); rp -> Draw( ); // átadjuk az OpenGL-nek }
OpenGL LineList class LineList : public RenderPrimitive { void Draw( ) { glColor3d( color.R, color.G, color.B ); glBegin( GL_LINE_STRIP ); for( i = 0; i < npoints; i++ ) glVertex2d(points[i].x, points[i].y); glEnd( ); glFlush( ); } };
OpenGL: primitívek GL_LINES GL_LINE_STRIP GL_POINTS GL_POLYGON GL_LINE_LOOP GL_QUADS GL_TRIANGLES GL_QUAD_STRIP GL_TRIANGLE_FAN GL_TRIANGLE_STRIP
Első kisfeladat Írjon görbesimító programot C++-ban OpenGL és GLUT felhasználásával. Az windows ablak háttérszíne kék, felbontását szabadon megválaszthatják. A program egy "pontok.txt" nevű ascii fájlt olvas be, amelynek első sorában egy int van (a pontok száma), amit ennyi sor követ, minden sorban két float számmal, amelyek a pontok x,y világkoordinátáit tartalmazzák. A program ezen csúcspontokra egy zárt töröttvonalat illeszt és egy (0,0),(100,100) sarokpontokkal definiált ablakú kamerával lefényképezi, az eredményt a képernyő windows ablakában megjeleníti. A zárt töröttvonalat fehér színnel kell felrajzolni. Ha a felhasználó a bal egér gombbal ráklikkel a zárt töröttvonal által határolt területre, a program Catmull-Clark algoritmussal simít egyet a töröttvonalon. Jobb egérklikk pedig csökkenti a simítás mértékét. A maximális simítás mértéke legalább 3, azon túl korlátozható. A zárt töröttvonal által határolt terület pontjai azok, amelyekhez a végtelenből érkezve páratlanször lépjük át a töröttvonalat. A programot egyetlen C++ fájlban kell megírni, amit az exe-vel egyetemben szecsi@iit.bme.hu címre kell elküldeni október 26-ig