Uživatelské nástroje

Nástroje pro tento web


pitel:izg:lab06

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revizePředchozí verze
pitel:izg:lab06 [29. 07. 2013, 13.40:40] – file pitelpitel:izg:lab06 [30. 12. 2022, 13.43:01] (aktuální) – upraveno mimo DokuWiki 127.0.0.1
Řádek 1: Řádek 1:
 +====== 3D transformace ======
 +[[http://www.flickr.com/photos/pitel/2426848399|{{ http://farm4.static.flickr.com/3207/2426848399_c2e6c0f45a_o.png |3D transformace}}]]
  
 +<file cpp student.cpp>
 +///////////////////////////////////////////////////////////////////////////////
 +// Soubor studentskych funkci
 +///////////////////////////////////////////////////////////////////////////////
 +
 +#include "main.h"
 +
 +#include <cmath>
 +#include <cstdio>
 +#include <iostream>
 +
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// name spaces
 +
 +using namespace std;
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// prace s transformacni matici
 +///////////////////////////////////////////////////////////////////////////////
 +
 +class Matrix
 +{
 +  double data[16];
 +
 +public:
 +  // inicializuje matici na jednotkovou
 +  Matrix() { LoadIdentity(); }
 +  
 +  // pristup k "radku" matice
 +  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, co tam ma...
 +  void Print()
 +  {
 +    cout << "===========================" << endl;
 +    for (int i = 0; i < 4; i++) {
 +      for (int j = 0; j < 4; j++) {
 +        cout << ios_base::fixed << data[i*4 + j];
 +      }
 +      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 &trGetMatrix()
 +{
 +  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,yy,zz,ww)
 +  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,y1,z1   jeden vrchol ve 3D
 +//    x2,y2,z2   druhy vrchol
 +void ProjectLine(double x1, double y1, double z1,
 +                 double x2, double y2, double z2,
 +                 const S_RGBA &color)
 +{
 +  // cara se promitne tak, ze se promitnou jeji krajni body
 +  int u1,v1,u2,v2;
 +  ProjectVertex(u1, v1, x1, y1, z1);
 +  ProjectVertex(u2, v2, x2, y2, z2);
 +  DrawLine(u1, v1, u2, v2, color);
 +}
 +
 +// vykresli trojuhelnik zadany ve 3D po promitnuti transformaci
 +//    x1,y1,z1   jeden vrchol ve 3D
 +//    x2,y2,z2   druhy vrchol
 +//    x3,y3,z3   treti vrchol
 +void ProjectTriangle(double x1, double y1, double z1,
 +                     double x2, double y2, double z2,
 +                     double x3, double y3, double z3,
 +                     const S_RGBA &color)
 +{
 +  // promitnou vrcholy trojuhelniku
 +  int u1, v1, u2, v2, u3, v3;
 +  ProjectVertex(u1, v1, x1, y1, z1);
 +  ProjectVertex(u2, v2, x2, y2, z2);
 +  ProjectVertex(u3, v3, x3, y3, z3);
 +
 +  // testujeme odvracene/privracene trojuhelniky?
 +  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, v1, u2, v2, color);
 +  DrawLine(u2, v2, u3, v3, color);
 +  DrawLine(u3, v3, u1, v1, color);
 +}
 +
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// funkce DrawObject
 +// - vykresli objekt transformovany aktivni transformacni matici
 +
 +void DrawObject(const S_RGBA &color)
 +{
 +  // postupne vykresleni vsech trojuhelniku
 +  T_Triangles::iterator end = triangles.end();
 +  for( T_Triangles::iterator it = triangles.begin(); it != end; ++it )
 +  {
 +    int v0 = it->v[0], v1 = it->v[1], v2 = it->v[2];
 +    ProjectTriangle(vertices[v0].x, vertices[v0].y, vertices[v0].z,
 +                    vertices[v1].x, vertices[v1].y, vertices[v1].z,
 +                    vertices[v2].x, vertices[v2].y, vertices[v2].z,
 +                    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, 0.0, scene_move_z);
 +
 +  // 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 "zrcadla" modrou barvou
 +  ProjectLine(0, -2, -2, 0,  2, -2, COLOR_BLUE);
 +  ProjectLine(0,  2, -2, 0,  2,  2, COLOR_BLUE);
 +  ProjectLine(0,  2,  2, 0, -2,  2, COLOR_BLUE);
 +  ProjectLine(0, -2,  2, 0, -2, -2, COLOR_BLUE);
 +
 +  // 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);
 +}
 +</file>
/var/www/wiki/data/attic/pitel/izg/lab06.1375105240.txt.bz2 · Poslední úprava: 30. 12. 2022, 13.43:01 (upraveno mimo DokuWiki)