Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.
Obě strany předchozí revizePředchozí verze | |||
pitel:izg:lab06 [29. 07. 2013, 13.40:40] – file pitel | pitel:izg:lab06 [30. 12. 2022, 13.43:01] (aktuální) – upraveno mimo DokuWiki 127.0.0.1 | ||
---|---|---|---|
Řádek 1: | Řádek 1: | ||
+ | ====== 3D transformace ====== | ||
+ | [[http:// | ||
+ | <file cpp student.cpp> | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // Soubor studentskych funkci | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | #include " | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // name spaces | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // prace s transformacni matici | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | class Matrix | ||
+ | { | ||
+ | double data[16]; | ||
+ | |||
+ | public: | ||
+ | // inicializuje matici na jednotkovou | ||
+ | Matrix() { LoadIdentity(); | ||
+ | | ||
+ | // pristup k " | ||
+ | double *operator [] (int row) { return (data + row*4); } | ||
+ | |||
+ | // nastavi matici na jednotkovou | ||
+ | void LoadIdentity() | ||
+ | { | ||
+ | for (int i = 0; i < 4; i++) | ||
+ | for (int j = 0; j < 4; j++) | ||
+ | data[i*4 + j] = (i == j) ? 1.0 : 0.0; | ||
+ | } | ||
+ | |||
+ | // kdyby si to nekdo chtel vypsat, aby zkontroloval, | ||
+ | void Print() | ||
+ | { | ||
+ | cout << " | ||
+ | for (int i = 0; i < 4; i++) { | ||
+ | for (int j = 0; j < 4; j++) { | ||
+ | cout << ios_base:: | ||
+ | } | ||
+ | cout << endl; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // aktivni matice | ||
+ | |||
+ | Matrix transf; | ||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // operace nad aktivni matici | ||
+ | |||
+ | // nastavi transformaci na zadanou matici | ||
+ | void trSetMatrix(const Matrix &m) | ||
+ | { | ||
+ | transf = m; | ||
+ | } | ||
+ | |||
+ | // vraci aktualni transformaci | ||
+ | const Matrix & | ||
+ | { | ||
+ | return transf; | ||
+ | } | ||
+ | |||
+ | // resetuje transformacni matici na jednotkovou | ||
+ | void trLoadIdentity() | ||
+ | { | ||
+ | transf.LoadIdentity(); | ||
+ | } | ||
+ | |||
+ | // skladani transformaci (aktualni transformaci vynasobi zadanou matice) | ||
+ | void trMultMatrix(Matrix &m) | ||
+ | { | ||
+ | Matrix newtransf; | ||
+ | for (int i = 0; i < 4; i++) { | ||
+ | for (int j = 0; j < 4; j++) { | ||
+ | newtransf[i][j] = 0; | ||
+ | for (int x = 0; x < 4; x++) { | ||
+ | newtransf[i][j] += m[i][x] * transf[x][j]; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | trSetMatrix(newtransf); | ||
+ | } | ||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // funkce, ktere provadeji ruzne druhy transformace | ||
+ | |||
+ | // vynasobi hlavni matici translacni matici (ktera objekt posouva o zadane vzdalenosti) | ||
+ | void trTranslate(double dx, double dy, double dz) | ||
+ | { | ||
+ | Matrix m; | ||
+ | |||
+ | m[3][0] = dx; | ||
+ | m[3][1] = dy; | ||
+ | m[3][2] = dz; | ||
+ | |||
+ | trMultMatrix(m); | ||
+ | } | ||
+ | |||
+ | // vynasobi hlavni matici rotacni matici kolem osy Y | ||
+ | void trRotateY(double angle) | ||
+ | { | ||
+ | Matrix m; | ||
+ | |||
+ | // aby se goniometricke funkce nepocitaly dvakrat, kdyz to staci jednou... | ||
+ | double sina = sin(angle); | ||
+ | double cosa = cos(angle); | ||
+ | |||
+ | m[0][0] = cosa; | ||
+ | m[0][2] = sina; | ||
+ | m[2][0] = -sina; | ||
+ | m[2][2] = cosa; | ||
+ | |||
+ | trMultMatrix(m); | ||
+ | } | ||
+ | |||
+ | // vynasobi hlavni matici rotacni matici kolem osy X | ||
+ | void trRotateX(double angle) | ||
+ | { | ||
+ | Matrix m; | ||
+ | | ||
+ | // aby se goniometricke funkce nepocitaly dvakrat, kdyz to staci jednou... | ||
+ | double sina = sin(angle); | ||
+ | double cosa = cos(angle); | ||
+ | | ||
+ | m[1][1] = cosa; | ||
+ | m[1][2] = sina; | ||
+ | m[2][1] = -sina; | ||
+ | m[2][2] = cosa; | ||
+ | |||
+ | trMultMatrix(m); | ||
+ | } | ||
+ | |||
+ | // vynasobi hlavni matici projekcni matici, ktera zaridi PERSPEKTIVNI promitani | ||
+ | void trProjectionPerspective(double d) | ||
+ | { | ||
+ | Matrix m; | ||
+ | |||
+ | m[2][2] = 0.0; | ||
+ | m[2][3] = 1.0 / d; | ||
+ | |||
+ | trMultMatrix(m); | ||
+ | } | ||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // funkce k vykresleni promitnute usecky, apod. | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | // promitne bod ve 3D | ||
+ | // x,y,z souradnice ve 3D | ||
+ | // u,v souradnice na obrazovce promitnute matici transf | ||
+ | void ProjectVertex(int &u, int &v, double x, double y, double z) | ||
+ | { | ||
+ | // vynasobeni vektoru (x,y,z,1) transformacni matici - vyjde vektor (xx, | ||
+ | double xx = x*transf[0][0] + y*transf[1][0] + z*transf[2][0] + 1*transf[3][0]; | ||
+ | double yy = x*transf[0][1] + y*transf[1][1] + z*transf[2][1] + 1*transf[3][1]; | ||
+ | double ww = x*transf[0][3] + y*transf[1][3] + z*transf[2][3] + 1*transf[3][3]; | ||
+ | |||
+ | // homogenni souradnice | ||
+ | xx /= ww; | ||
+ | yy /= ww; | ||
+ | | ||
+ | // vypocteni promitnutych souradnic - meritko odvozeno od frame_h v obou osach... | ||
+ | u = int(xx + frame_w/2); | ||
+ | v = int(yy + frame_h/2); | ||
+ | } | ||
+ | |||
+ | // vykresli usecku zadanou ve 3D po promitnuti transformaci | ||
+ | // x1, | ||
+ | // x2, | ||
+ | void ProjectLine(double x1, double y1, double z1, | ||
+ | | ||
+ | const S_RGBA &color) | ||
+ | { | ||
+ | // cara se promitne tak, ze se promitnou jeji krajni body | ||
+ | int u1, | ||
+ | ProjectVertex(u1, | ||
+ | ProjectVertex(u2, | ||
+ | DrawLine(u1, | ||
+ | } | ||
+ | |||
+ | // vykresli trojuhelnik zadany ve 3D po promitnuti transformaci | ||
+ | // x1, | ||
+ | // x2, | ||
+ | // x3, | ||
+ | void ProjectTriangle(double x1, double y1, double z1, | ||
+ | | ||
+ | | ||
+ | const S_RGBA &color) | ||
+ | { | ||
+ | // promitnou vrcholy trojuhelniku | ||
+ | int u1, v1, u2, v2, u3, v3; | ||
+ | ProjectVertex(u1, | ||
+ | ProjectVertex(u2, | ||
+ | ProjectVertex(u3, | ||
+ | |||
+ | // testujeme odvracene/ | ||
+ | if (back_face_culling) | ||
+ | { | ||
+ | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
+ | // MISTO PRO STUDENTSKOU PRACI | ||
+ | // - zjistete zda je trojuhelnik odvraceny nebo privraceny | ||
+ | // - pokud neni viditelny (= odvraceny), tak nic nekreslete | ||
+ | // - test je nutne prevratit pokud promenna invert_culling = -1 | ||
+ | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
+ | int vect11 = u2 - u1; | ||
+ | int vect12 = v2 - v1; | ||
+ | int vect21 = u3 - u1; | ||
+ | int vect22 = v3 - v1; | ||
+ | int normal = (vect11 * vect22 - vect12 * vect21) * invert_culling; | ||
+ | if (normal > 0) { | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // vykresleni (pouze viditelne viditelne trojuhelniky) | ||
+ | DrawLine(u1, | ||
+ | DrawLine(u2, | ||
+ | DrawLine(u3, | ||
+ | } | ||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // funkce DrawObject | ||
+ | // - vykresli objekt transformovany aktivni transformacni matici | ||
+ | |||
+ | void DrawObject(const S_RGBA &color) | ||
+ | { | ||
+ | // postupne vykresleni vsech trojuhelniku | ||
+ | T_Triangles:: | ||
+ | for( T_Triangles:: | ||
+ | { | ||
+ | int v0 = it-> | ||
+ | ProjectTriangle(vertices[v0].x, | ||
+ | vertices[v1].x, | ||
+ | vertices[v2].x, | ||
+ | color); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // funkce DrawScene() volana z main.cpp | ||
+ | // - vykresli celou scenu vcetne dvou vlozenych objektu | ||
+ | |||
+ | void DrawScene() | ||
+ | { | ||
+ | // vymazani frame bufferu | ||
+ | ClearBuffer(); | ||
+ | |||
+ | // vycistit hlavni matici - do definovaneho stavu | ||
+ | trLoadIdentity(); | ||
+ | |||
+ | // nastavit projekcni matici | ||
+ | trProjectionPerspective(CAMERA_DIST); | ||
+ | |||
+ | // posuv cele sceny | ||
+ | trTranslate(0.0, | ||
+ | |||
+ | // natoceni cele sceny - jen ve dvou smerech - mys je jen 2D... :( | ||
+ | trRotateX(scene_rot_x * 0.01); | ||
+ | trRotateY(scene_rot_y * 0.01); | ||
+ | |||
+ | Matrix backuptransf = transf; | ||
+ | |||
+ | // vykresleni " | ||
+ | ProjectLine(0, | ||
+ | ProjectLine(0, | ||
+ | ProjectLine(0, | ||
+ | ProjectLine(0, | ||
+ | |||
+ | // vykresli objekt cervene | ||
+ | // pridame k nastaveni sceny umisteni a natoceni objektu | ||
+ | trTranslate(obj_move_x * 0.015, obj_move_y * 0.015, 0.0); | ||
+ | trRotateX(obj_rot_x * 0.01); | ||
+ | trRotateY(obj_rot_y * 0.01); | ||
+ | |||
+ | // a s tim co vznikne promitneme nas objekt | ||
+ | invert_culling = 1; | ||
+ | DrawObject(COLOR_RED); | ||
+ | |||
+ | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
+ | // MISTO PRO STUDENTSKOU PRACI | ||
+ | // - vykresleni objektu soumerneho podle modre roviny | ||
+ | // - volejte DrawObject() | ||
+ | // - pouzijte barvu COLOR_RED2 | ||
+ | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
+ | Matrix mirror; | ||
+ | invert_culling = -1; | ||
+ | transf = backuptransf; | ||
+ | mirror[0][0] = -1; | ||
+ | trMultMatrix(mirror); | ||
+ | trTranslate(obj_move_x * 0.015, obj_move_y * 0.015, 0.0); | ||
+ | trRotateX(obj_rot_x * 0.01); | ||
+ | trRotateY(obj_rot_y * 0.01); | ||
+ | DrawObject(COLOR_RED2); | ||
+ | } | ||
+ | </ |