320 likes | 479 Views
2D grafikus rendszerek. Szirmay-Kalos László. 2D grafikus editor: GUI, use-case, dinamikus modell. L. LD. L. LU. L. R. MouseLDown első pont MouseLDown második ... MouseLDown n. MouseRDown utolsó. MouseLDown pick? MouseMove mozgat MouseLUp letesz.
E N D
2D grafikus rendszerek Szirmay-Kalos László
2D grafikus editor: GUI, use-case, dinamikus modell L LD L LU L R MouseLDown első pont MouseLDown második ... MouseLDown n. MouseRDown utolsó MouseLDown pick? MouseMove mozgat MouseLUp letesz
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) kamera Virtuális világ Kép frissités Kurzor (xp, yp) vektorizáció 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
Controller + View Osztálydiagram Scene actobject InputPipe() Pick() Render() Window state MouseLD() MouseLU() MouseMov() PutPixel() Object transform AddPrimitive() GetPrimitive() tároló tároló tároló RenderPrimitive Transform() Clip() Draw() Primitive color AddPoint() Vectorize() Point x,y Camera window viewport ClipWindow() ViewTransform() Op.rendszer függő Polyline Vectorize() Curve r(t) Vectorize() Polygon Vectorize() Transform float m[3][3] Rect x,y,w,h RPolyline Clip() Draw() RPolygon Clip() Draw() RPoints Clip() Draw() Bezier r(t) B-Spline r(t) Color float R, G, B
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; } }; h (x,y) w vw/ww0 0 0 vh/wh 0 vx-wxvw/wwvy-wyvh/wh 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; } }; t1= 0,t2 ,... ,tn=1 r(ti)
Bezier görbe: r(t) () n 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; } }; Bi(t) = ti(1-t)n-i i r(t) = S Bi(t) ri
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 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)} }; RenderPrimitive
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 ); }
Operációs rendszer illesztés Operációs és ablakozó rendszer (Windows) MouseLD() MouseLU() MouseMov() GLUT Alkalmazás Rasztertár OpenGL transzform vágás raszterizáció PutPixel()
GLUT/OpenGL alkalmazás Ablak létrehozás callback regisztráció Operációs és ablakozó rendszer (Windows) main GLUT DisplayFunc KeyboadFunc SpecialFunc callback-ek ReshapeFunc Rasztertár OpenGL MouseFunc grafikus hardver MotionFunc IdleFunc kimeneti csővezeték
OpenGL szintaxis gl könyvtár része 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
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 transzformációk(2D-s utánérzés) Normalizált képernyő x y z=0 h=1 Modelview mátrix Projection mátrix Homogén osztás Viewport transzf. képernyő raszterizáció vágás TV TM 1,1 -1,-1
OpenGL mátrix • OpenGL specifikáció: • Mi:
#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); glLoadIdentity( ); gluOrtho2D(0., 100., 0., 100.); // fő hurok glutMainLoop(); } (100,100) OpenGL/ GLUT inicializálás 200 200 (100,100) ablak (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( ); } } ablak (100,100) (0,0) (200,200) Ablak újrarajzoláskor elveszik!
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(); } } 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; glutPostRedisplay(); } } Nem rajzol feleslegesensokszor
2D grafikus editor GLUT/OpenGL-lel Operációs és ablakozó rendszer GLUT main DisplayFunc Redraw MouseFunc MouseDown MotionFunc MouseMove OpenGL Rasztertár RGB transzform vágás raszterizáció Raszter műveletek
Osztálydiagram RenderPrimitive Transform() Clip() Draw() RPolyLine Clip() Draw() RPolygon Clip() Draw() RPointList Clip() Draw() Scene actobject InputPipe() Pick() Render() Window state MouseLD() MouseLU() MouseMov() PutPixel() Object transform AddPrimitive() GetPrimitive() Primitive color AddPoint() Draw() Point x,y Camera ClipWindow() ViewTransform() window viewport Polyline Draw() Curve r(t) Draw() Polygon 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 } } } ux uy 0 vx vy 0 ox oy 1 [x, y, 1] ux uy 00 vx vy 0 0 0 0 1 0 ox oy 0 1 [x, y, 0, 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_LINES GL_LINE_STRIP GL_POINTS GL_POLYGON GL_LINE_LOOP GL_QUADS GL_TRIANGLES GL_QUAD_STRIP GL_TRIANGLE_FAN GL_TRIANGLE_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! //================================================================================
#include <math.h> #include <stdlib.h> #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> // A GLUT-ot le kell tolteni //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Innentolmodosithatod... // Nev : <VEZETEKNEV(EK)> <KERESZTNEV(EK)>, Neptun : <NEPTUN KOD> //-------------------------------------------------------- voidonInitialization( ) { } // Inicializacio, voidonDisplay( ) {// Rajzolas glClearColor(0.1f, 0.2f, 0.3f, 1.0f); // torlesiszinbeallitasa glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // kepernyotorles // ... glutSwapBuffers(); // Buffercsere: rajzolasvege } voidonKeyboard(unsignedcharkey, int x, int y) { // Billentyuzetesemeny if (key == 'd') glutPostRedisplay( ); // dbeture rajzold ujra a kepet } voidonMouse(int button, intstate, int x, int y) {// Eger esemeny if (button == GLUT_LEFT && state == GLUT_DOWN); } voidonIdle( ) {// `Idle' esemenykezelo, jelzi, hogy az ido telik longtime = glutGet(GLUT_ELAPSED_TIME); // program inditasaota eltelt ido } // ...Idaigmodosithatod //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Házi
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 + melysegbuffer 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); // Esemenykezelokregisztralasa glutMouseFunc(onMouse); glutIdleFunc(onIdle); glutKeyboardFunc(onKeyboard); glutMainLoop(); // Esemenykezelo hurok return 0; }