2D grafikus rendszerek Szirmay-Kalos László
2D grafikus editor: GUI, use-case, dinamikus modell L L L R LD LU MouseLDown első pont MouseLDown második... MouseLDown n. MouseRDown utolsó MouseLDownpick? MouseMovemozgat MouseLUpletesz
Funkcionális modell Kép frissités rasztertár Pixel műveletek Raszteri- záció Vágás Világ- képtér Modellezési transzf. Világ- lokális mod. Képtér- világ Eszköz- képtér Virtuális világ T V -1 T M -1 TVTV TMTM Kurzor (xp, yp) Kimeneti csővezeték Bemeneti csővezeték Eszköz koord. (xe, ye) kamera vektorizáció
Osztálydiagram Window state MouseLD() MouseLU() MouseMov() PutPixel() Camera window viewport ClipWindow() ViewTransform() Object transform AddPrimitive() GetPrimitive() Primitive color AddPoint() Vectorize() Point x,y Polyline Vectorize() Curve r(t) Vectorize() Polygon Vectorize() RenderPrimitive Transform() Clip() Draw() RPoints Clip() Draw() RPolyline Clip() Draw() RPolygon Clip() Draw() Bezier r(t) B-Spline r(t) Scene actobject InputPipe() Pick() Render() tároló Op.rendszer függő Controller + View Color float R, G, B Rect x,y,w,h Transform float m[3][3]
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( ); }
Ablak-nézet transzformáció class Camera { Rect Viewport, Window; Transform ViewTransform( ) { Transform t = return t; } Rect ClipWindow( ) { return Viewport; } }; (x, y)(x, y) w h v w /w w 0 0 v h /w h 0 v x -w x v w /w w v y -w y v h /w h 1
Vektorizáció class Curve : Primitive { virtual Point r( float t ) = 0; RenderPrimitive Vectorize( ) { RPolyLine * polyline = new RPolyLine(); for(int i = 0; i <= NVECTOR; i++) { float t = (float)i / NVECTOR; polyline -> AddPoint( r( t ) ); } return polyline; } }; r(ti)r(ti) t 1 = 0, t 2,..., t n =1
Bezier görbe: r(t) class Bezier : Curve { Point r( float t ) { Point rr(0, 0); int n = npoints – 1; for(int i = 0; i < npoints; i++) { float Bi = 1; for(int j = 1; j <= i; j++) Bi *= (float)(n-j+1)/j; Bi *= pow(t, i) * pow(1-t, n-i); rr += points[i] * Bi; } return rr; } }; B i (t) = t i ( 1-t) n-i ( )( ) n i r(t) = B i (t) r i
RenderPrimitive class RenderPrimitive { Point * points; Colorcolor; void Transform( Transform T ) { for each point i do points[i].Transform( T ); } virtual Bool Clip( Rect cliprect ) = 0; virtual void Draw( ) = 0; }; class RPolyLine : public RenderPrimitive { Bool Clip( Rect cliprect ) { Cohen-Sutherland vágás } void Draw( ) { Szakaszrajzoló algoritmus: PutPixel(X, Y, color) } }; class RPolygon : public RenderPrimitive { Bool Clip( Rect cliprect ) { Sutherland-Hodgeman vágás } void Draw( ) { Területkitöltő algoritmus: PutPixel(X, Y, color) } };
Bemeneti csővezeték: pontok beépítése a virtuális világba Scene :: InputPipeline( int X, int Y ) { if ( !actobject ) actobject = AddObject( ); Transform Tm = actobject -> Transform( ); Transform Tv = camera.ViewTransform( ); Transform Tci = (Tm * Tv).Invert( ); Point p = Point(X, Y).Transform( Tci ); actobject -> GetPrimitive( ) -> AddPoint(p); } Window :: MouseLD( int X, int Y ) {... ha az állapot szerint a pontot be kell építeni scene.InputPipeline( X, Y ); scene.Render(); // visszacsatolás }
Primitív (objektum) kiválasztása Scene :: Pick( int X, int 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; return; } } Window :: MouseLD( X, Y ) {... ha az állapot szerint kiválasztás: scene.Pick( X, Y ); }
OpenGL Operációs rendszer illesztés transzform Rasztertár Operációs és ablakozó rendszer (Windows) vágás MouseLD() MouseLU() MouseMov() PutPixel() Alkalmazás raszterizáció GLUT
GLUT/OpenGL Rasztertár Operációs és ablakozó rendszer (Windows) GLUT OpenGL grafikus hardver main DisplayFunc KeyboadFunc IdleFunc alkalmazás SpecialFunc ReshapeFunc MouseFunc MotionFunc Ablak létrehozás callback regisztráció callback-ek kimeneti csővezeték
OpenGL szintaxis glVertex3dv( … ) 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 gl könyvtár része
glX, wglglu Ablakozó – OpenGL – alkalmazás elhelyezkedése hw applikáció gl GLUT X v. MS-Win Ablak-kezelés widgetek Ablakozó- gl híd Utility-k, tesszellátorok Window menedzsment
OpenGL transzformációk (2D-s utánérzés) x y z=0 h=1 Modelview mátrix Projection mátrix Homogén osztás Viewport transzf. képernyő Normalizált képernyő -1,-1 1,1 TVTV TMTM vágás raszterizáció
OpenGL mátrix l OpenGL specifikáció: l Mi:
OpenGL/ GLUT inicializálás #include #include // 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); glLoadIdentity( ); gluOrtho2D(0., 100., 0., 100.); // fő hurok glutMainLoop(); } ablak (0,0) (100,100) 200
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( ); } (100,100) ablak Ablak újrarajzoláskor elveszik! (0,0) (200,200)
A háromszög újrarajzoláskor megmarad bool haromszog = false; void ReDraw( ) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); if ( haromszog ) { 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( ); } void Keyboard(unsigned char key, int x, int y) { if (key == 'd') { haromszog = true; ReDraw( ); }
Nem rajzol feleslegesen sokszor bool haromszog = false; void ReDraw( ) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); if ( haromszog ) { 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( ); } void Keyboard(unsigned char key, int x, int y) { if (key == 'd') { haromszog = true; glutPostRedisplay(); }
2D grafikus editor GLUT/OpenGL-lel transzform vágás raszterizáció Raszter műveletek Rasztertár RGB Operációs és ablakozó rendszer GLUT main Redraw MouseDown MouseMove DisplayFunc MouseFunc MotionFunc OpenGL
Osztálydiagram Window state MouseLD() MouseLU() MouseMov() PutPixel() Scene actobject InputPipe() Pick() Render() Camera ClipWindow() ViewTransform() window viewport Object transform AddPrimitive() GetPrimitive() Primitive color AddPoint() Draw() Point x,y Polyline Draw() Curve r(t) Draw() Polygon Draw() RenderPrimitive Transform() Clip() Draw() RPointList Clip() Draw() RPolyLine Clip() Draw() RPolygon Clip() Draw() Bezier r(t) B-Spline r(t)
GLUT: inicializálás main(argc, argv) { glutInitWindowSize(200, 200); glutInitWindowPosition(100, 100); glutInit(&argc, argv); glutInitDisplayMode( GLUT_RGB ); glutCreateWindow("2D graphics editor"); glutMouseFunc(MouseDown); // callback glutMotionFunc(MouseMove); 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 MouseDown( int button, int state, int x, int y ) { if (button == GLUT_LEFT && state == GLUT_DOWN) window.MouseLD(x, y); … } void MouseMove( int x, int y ) { window.MouseMov(x, y); }
OpenGL Render Scene :: Render ( ) { glViewport(camera.viewport.Left(), camera.viewport.Bottom(), camera.viewport.Width(), camera.viewport.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 { glLoadIdentity(); // 4x4 matrix glMultMatrixf(obj->Transform()); for each primitive p of object obj { p -> Draw( ); // OpenGL-nek } u x u y 0 v x v y 0 o x o y 1 u x u y 0 0 v x v y o x o y 0 1 [x, y, 0, 1] [x, y, 1]
Curve rajzolás class Curve : Primitive { void Draw( ) { glColor3d( color.R, color.G, color.B ); glBegin( GL_LINE_STRIP ); for(int i = 0; i <= NVECTOR; i++) { float t = (float)i / NVECTOR; Point p = r( t ); glVertex2d(p.x, p.y); } glEnd( ); } };
OpenGL: primitívek GL_POINTS GL_LINES GL_LINE_STRIP GL_LINE_LOOP GL_POLYGON GL_TRIANGLE_STRIP GL_TRIANGLES GL_TRIANGLE_FAN GL_QUADS GL_QUAD_STRIP
Házi //================================================================================ // Szamitogepes grafika hazi feladat keret. Ervenyes 2010-tol. // A //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // sorokon beluli reszben celszeru garazdalkodni, mert a tobbit ugyis toroljuk. // A Hazi feladat csak ebben a fajlban lehet. // Tilos: // - mast "beincludolni", illetve mas konyvtarat hasznalni // - faljmuveleteket vegezni (printf is fajlmuvelet!) // // Csak az órán elhangzott gl/glu/glut fuggvenyek hasznalhatok: // glBegin, glVertex[2|3]f, glColor3f, glNormal3f, glTexCoord2f, glEnd, glDrawPixels // glViewport, glMatrixMode, glLoadIdentity, glMultMatrixf, gluOrtho2D, // glTranslatef, glRotatef, glScalef, gluLookAt, gluPerspective, // glPushMatrix,glPopMatrix, // glMaterialfv, glMaterialfv, glMaterialf, glLightfv // glGenTextures, glBindTexture, glTexParameteri, glTexImage2D, glTexEnvi, // glShadeModel, // glEnable/Disable a kovetkezokre: GL_LIGHT[0..7], // GL_LIGHTING, GL_NORMALIZE, GL_DEPTH_TEST, GL_CULL_FACE, GL_TEXTURE_2D, GL_BLEND, // // A házi feladat felesleges programsorokat NEM tartalmazhat! //================================================================================
Házi #include #include // A GLUT-ot le kell tolteni //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Innentol modosithatod... // Nev :, Neptun : // void onInitialization( ) { } // Inicializacio, void onDisplay( ) {// Rajzolas glClearColor(0.1f, 0.2f, 0.3f, 1.0f);// torlesi szin beallitasa glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // kepernyo torles //... glutSwapBuffers(); // Buffercsere: rajzolas vege } void onKeyboard(unsigned char key, int x, int y) { // Billentyuzet esemeny if (key == 'd') glutPostRedisplay( ); // d beture rajzold ujra a kepet } void onMouse(int button, int state, int x, int y) {// Eger esemeny if (button == GLUT_LEFT && state == GLUT_DOWN); } void onIdle( ) {// `Idle' esemenykezelo, jelzi, hogy az ido telik long time = glutGet(GLUT_ELAPSED_TIME); // program inditasa ota eltelt ido } //...Idaig modosithatod //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Még mindig házi // A C++ program belepesi pontja, nem bántani! int main(int argc, char **argv) { glutInit(&argc, argv); // GLUT inicializalasa glutInitWindowSize(600, 600); glutInitWindowPosition(100, 100); // 8 bites R,G,B,A + dupla buffer + melyseg buffer glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("Grafika hazi feladat"); glMatrixMode(GL_MODELVIEW); // A MODELVIEW egysegmatrix glLoadIdentity(); glMatrixMode(GL_PROJECTION); // A PROJECTION egysegmatrix glLoadIdentity(); onInitialization();// Az altalad irt inicializalas glutDisplayFunc(onDisplay); // Esemenykezelok regisztralasa glutMouseFunc(onMouse); glutIdleFunc(onIdle); glutKeyboardFunc(onKeyboard); glutMainLoop();// Esemenykezelo hurok return 0; }