Трехмерная графіка.
Теория
Как відомо, будь-яке аффинное перетворення на тривимірному просторі то, можливо представлено як суперпозиции обертань розтягань, відображень і переносів. Тому досить докладно описати матриці лише цих останніх перетворень. Здесь a>0 — коефіцієнт розтяги (стискування) вздовж осі абсцисс, b>0-коэффициент розтяги (стискування) вздовж осі ординат, y>0-коэффициент розтяги (стискування) вздовж осі… Читати ще >
Трехмерная графіка. Теория (реферат, курсова, диплом, контрольна)
Трехмерная графіка.
Краткие теоретичні відомості.
Каждая точка простору (крім початковій точки Про) то, можливо задана четвіркою одночасно не рівних нулю чисел ((x, y, z, 1) чи, більш загальне твердження, (hx, hy, hz, h), де ). Ця четвірка визначено однозначно з точністю до загального множника. Запропонований підхід дає можливість скористатися матричної записом й більш складних, тривимірних завданнях.
Как відомо, будь-яке аффинное перетворення на тривимірному просторі то, можливо представлено як суперпозиции обертань розтягань, відображень і переносів. Тому досить докладно описати матриці лише цих останніх перетворень.
A. Матриці обертання у просторі.
Матрица обертання навколо осі абсцис на кут q:
.
Матрица обертання навколо осі ординат на кут w:
.
Матрица обертання навколо осі аппликат на кут x:
.
Б. Матриця розтяги (стискування):
.
здесь a>0 — коефіцієнт розтяги (стискування) вздовж осі абсцисс, b>0-коэффициент розтяги (стискування) вздовж осі ординат, y>0-коэффициент розтяги (стискування) вздовж осі аппликат.
В. Матриця відображення .
Матрица відображення щодо площині xOy:
.
Матрица відображення щодо площині yOz:
.
Матрица відображення щодо площині zOx:
.
Г. Матриця перенесення :
.
Здесь (r, q, v)-вектор перенесення.
Заметим, що, як й у двовимірному разі, все виписані матриці не вырождены.
Ортографическая проекція — картинна площину збігаються з одній з координатних площин чи паралельна їй. Матриця проектування вздовж осі Х на площину YOZ має вигляд.
.
В разі, якщо площину проектування паралельна координатної площині, необхідно помножити матрицю [Px] на матрицю зсуву. Маємо.
.
Аналогично записуються матриці проектування вздовж 2-х координатних осей:
.
Аксонометрическая проекція — які проектують прямі перпендикулярні картинної площини .
Различают три виду проекцій залежно від взаємної розташування площині проектування й координатних осей:
триметрия-нормальный вектор картинної площини утворює з ортами координатних осей попарно різні углы (рис.15);
диметрия-два кута між нормалью картинної площини і координатными осями рівні (рис. 16).
— изометрия-все три кута між нормалью картинної площини і координатными осями рівні (рис. 17).
Каждый із трьох видів зазначених проекцій виходить комбінацією поворотів, яку слід паралельне проектування.
Перспективные (центральні) проекції будуються складніше. Припустимо що киселинсько-берестський осередок проектування лежить на жіночих осі Z — З (0,0,c) а площину проектування збігаються з координатної площиною XOY (рис. 19). Візьмемо у просторі довільну точку M (x, y, z), проведемо неї й ставлячи крапку З пряму і запишемо її параметричні рівняння. Маємо:
X`= xt, Y`=yt, Z`= c+(z-c)t.
Найдем координати точки перетину цієї прямий з площиною XOY. З того, що z`=0, отримуємо.
.
Тот ж найбільш результат ми матимемо, залучаючи матрицю.
.
В насправді,.
.
Mатрица проектування, звісно, вырождена; матриця ж відповідного перспективного преобразования (без проектування) має такий вигляд.
.
Язык З++ надає дуже зручні кошти, дозволяють помітно спростити роботи з векторами і перетвореннями у просторі.
Рассмотрим реалізацію роботи з векторами.
// Файл vector.h.
#ifndef __VECTOR__#define __VECTOR__#include class Vector{public: double x, y, z; Vector () {}; Vector (double v) { x = y = z = v; };
Vector (const Vector& v) { x = v. x; y = v. y; z = v. z; };
Vector (double vx, double vy, double vz) { x = vx; y = vy; z = vz; };
Vector& operator = (const Vector& v) { x = v. x; y = v. y; z = v. z;
return *this; }.
Vector& operator = (double f) { x = y = z = f; return *this; };
Vector operator — () const;
Vector& operator += (const Vector&);
Vector& operator -= (const Vector&);
Vector& operator *= (const Vector&);
Vector& operator *= (double);
Vector& operator /= (double);
friend Vector operator + (const Vector&, const Vector&);
friend Vector operator — (const Vector&, const Vector&);
friend Vector operator * (const Vector&, const Vector&);
friend Vector operator * (double, const Vector&);
friend Vector operator * (const Vector&, double);
friend Vector operator / (const Vector&, double);
friend Vector operator / (const Vector&, const Vector&);
friend double operator & (const Vector& u, const Vector& v).
{ return u. x * v. x + u. y * v. y + u. z * v. z; };
friend Vector operator ^ (const Vector&, const Vector&);
double operator ! () { return (double) sqrt (x * x + y * y + z * z); };
double& operator [] (int n) { return *(&x + n); };
int operator < (double v) { return x < v && y < v && z < v; };
int operator > (double v) { return x > v && y > v && z > v; };
};
class Ray.
{.
public:
Vector Org;
Vector Dir;
Ray () {};
Ray (Vector& o, Vector& d) { Org = o, Dir = d; };
Vector Point (double t) { return Org + Dir * t; };
};
inline Vector Vector: operator — () const.
{.
return Vector (-x, -y, -z);
}.
inline Vector operator + (const Vector& u, const Vector& v).
{.
return Vector (u.x + v. x, u. y + v. y, u. z + v. z);
}.
inline Vector operator — (const Vector& u, const Vector& v).
{.
return Vector (u.x — v. x, u. y — v. y, u. z — v. z);
}.
inline Vector operator * (const Vector& u, const Vector& v).
{.
return Vector (u.x * v. x, u. y * v. y, u. z * v. z);
}.
inline Vector operator * (const Vector& u, double f).
{.
return Vector (u.x * f, u. y * f, u. z * f);
}.
inline Vector operator * (double f, const Vector& v).
{.
return Vector (f * v. x, f * v. y, f * v. z);
}.
inline Vector operator / (const Vector& u, const Vector& v).
{.
return Vector (u.x / v. x, u. y / v. y, u. z / v. z);
}.
inline Vector operator / (const Vector& u, double f).
{.
return Vector (u.x / f, u. y / f, u. z / f);
}.
inline Vector& Vector: operator += (const Vector& v).
{.
x += v. x;
y += v. y;
z += v. z;
return *this;
}.
inline Vector& Vector: operator -= (const Vector& v).
{.
x -= v. x;
y -= v. y;
z -= v. z;
return *this;
}.
inline Vector& Vector: operator *= (const Vector& v).
{.
x *= v. x;
y *= v. y;
z *= v. z;
return *this;
}.
inline Vector& Vector: operator *= (double v).
{.
x *= v;
y *= v;
z *= v;
return *this;
}.
inline Vector& Vector: operator /= (double v).
{.
x /= v;
y /= v;
z /= v;
return *this;
}.
inline Vector Normalize (Vector& v) { return v / !v; }.
Vector RndVector ();
Vector& Clip (Vector& v);
#endif.
——————————————————————————————————————.
// Файл vector. срр
#include.
#include.
#include «vector.h «.
Vector operator ^ (const Vector& u, const Vector& v).
{.
return Vector (u.y * v. z — u. z * v. y,.
u.z * v. x — u. x * v. z,.
u.x * v. y — u. y * v. x);
}.
Vector RndVector ().
{.
Vector v (rand () — 0.5 * RAND_MAX,.
rand () — 0.5 * RAND_MAX,.
rand () — 0.5 * RAND_MAX);
return Normalize (v);
}.
Vector& Clip (Vector& v).
{.
if (v.x < 0.0) v. x = 0.0;
else.
if (v.x > 1.0) v. x = 1.0;
if (v.y < 0.0) v. y = 0.0;
else.
if (v.y > 1.0) v. y = 1.0;
if (v.z < 0.0) v. z = 0.0;
else.
if (v.z > 1.0) v. z = 1.0;
return v;
}.
С цією метою створюється клас Vector, яке у собі компоненти вектора, і цього класу переопределяются основні знаки операцій.
— - унарный мінус і поэлементное віднімання векторів;
+ - поэлементное складання векторів;
* - множення вектора на число;
* - поэлементное множення векторів;
/ - розподіл вектора на число;
/ - поэлементное розподіл векторів;
& - скалярне твір векторів;
^ - векторное твір;
! — довжина вектора;
[] - компонента вектора.
При цьому стандартні пріоритети операцій зберігаються.
Кроме операцій визначаються також існують деякі найпростіші функції до роботи з векторами:
Normalize — нормування вектора;
RndVector — отримання майже рівномірно розподіленого випадкового одиничного вектора;
Clip — відсікання вектора.
С використанням цього за природною та зручною формі записувати складні векторні висловлювання.
Аналогичным чином вводиться клас Matrix, службовець до подання матриць змін у тривимірному просторі. І тому класу також провадиться перевизначення основних знаків операцій.
//Файл matrix.h.
#ifndef __MATRIX__.
#define __MATRIX__.
#include «vector.h «.
class Matrix.
{.
public:
double x [4][4];
Matrix () {};
Matrix (double);
Matrix& operator += (const Matrix&);
Matrix& operator -= (const Matrix&);
Matrix& operator *= (const Matrix&);
Matrix& operator *= (double);
Matrix& operator /= (double);
void Invert ();
void Transpose ();
friend Matrix operator + (const Matrix&, const Matrix&);
friend Matrix operator — (const Matrix&, const Matrix&);
friend Matrix operator * (const Matrix&, double);
friend Matrix operator * (const Matrix&, const Matrix&);
friend Vector operator * (const Matrix&, const Vector&);
};
Matrix Translate (const Vector&);
Matrix Scale (const Vector&);
Matrix RotateX (double);
Matrix RotateY (double);
Matrix RotateZ (double);
Matrix Rotate (const Vector&, double);
Matrix MirrorX ();
Matrix MirrorY ();
Matrix MirrorZ ();
#endif.
//—————————————————————————————————————;
// Файл matrix.cpp.
#include #include «matrix.h «Matrix: Matrix (double v){ int j; for (int і = 0; і < 4; і++) for (j = 0; j < 4; j++) x [i][j] = (і == j)? v: 0.0; x [3][3] = 1;}void Matrix: Invert ().
{.
Matrix Out (1);
for (int і = 0; і < 4; і++) {.
double d = x [i][i];
if (d ≠ 1.0) {.
for (int j = 0; j < 4; j++) {.
Out.x [i][j] /= d;
x [i][j] /= d;
}.
}.
for (int j = 0; j < 4; j++) {.
if (j ≠ і) {.
if (x[j][i] ≠ 0.0) {.
double mulby = x[j][i];
for (int k = 0; k < 4; k++) {.
x [j][k] -= mulby * x [i][k];
Out.x [j][k] -= mulby * Out. x [i][k];
}.
}.
}.
}.
}.
*this = Out;
}.
void Matrix: Transpose ().
{.
double t;
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++).
if (і ≠ j) {.
t = x [i][j];
x [i][j] = x [j][i];
x [j][i] = t;
}.
}.
Matrix& Matrix: operator += (const Matrix& A).
{.
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++).
x [i][j] += A. x [i][j];
return *this;
}.
Matrix& Matrix: operator -= (const Matrix& A).
{.
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++).
x [i][j] -= A. x [i][j];
return *this;
}.
Matrix& Matrix: operator *= (double v).
{.
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++).
x [i][j] *= v;
return *this;
}.
Matrix& Matrix: operator *= (const Matrix& A).
{.
Matrix res = *this;
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++) {.
double sum = 0;
for (int k = 0; k < 4; k++).
sum += res. x [i][k] * A. x [k][j];
x [i][j] = sum;
}.
return *this;
}.
Matrix operator + (const Matrix& A, const Matrix& B).
{.
Matrix res;
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++).
res.x [i][j] = A. x [i][j] + B. x [i][j];
return res;
}.
Matrix operator — (const Matrix& A, const Matrix& B).
{.
Matrix res;
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++).
res.x [i][j] = A. x [i][j] - B. x [i][j];
return res;
}.
Matrix operator * (const Matrix& A, const Matrix& B).
{.
Matrix res;
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++) {.
double sum = 0;
for (int k = 0; k < 4; k++).
sum += A. x [i][k] * B. x [k][j];
res.x [i][j] = sum;
}.
return res;
}.
Matrix operator * (const Matrix& A, double v).
{.
Matrix res;
int j;
for (int і = 0; і < 4; і++).
for (j = 0; j < 4; j++).
res.x [i][j] = A. x [i][j] * v;
return res;
}.
Vector operator * (const Matrix& M, const Vector& v).
{.
Vector res;
res.x = v. x * M. x [0][0] + v. y * M. x [1][0] + v. z * M. x [2][0] + M. x [3][0];
res.y = v. x * M. x [0][1] + v. y * M. x [1][1] + v. z * M. x [2][1] + M. x [3][1];
res.z = v. x * M. x [0][2] + v. y * M. x [1][2] + v. z * M. x [2][2] + M. x [3][2];
double denom = v. x * M. x [0][3] + v. y * M. x [1][3] +.
v.z * M. x [2][3] + M. x[3][3];
if (denom ≠ 1.0).
res /= denom;
return res;
}.
Matrix Translate (const Vector& Loc).
{.
Matrix res (1);
res.x [3][0] = Loc. x;
res.x [3][1] = Loc. y;
res.x [3][2] = Loc. z;
return res;
};
Matrix Scale (const Vector& v).
{.
Matrix res (1);
res.x [0][0] = v. x;
res.x [1][1] = v. y;
res.x [2][2] = v. z;
return res;
};
Matrix RotateX (double Angle).
{.
Matrix res (1);
double Cosine = co (Angle);
double Sine = sin (Angle);
res.x [1][1] = Cosine;
res.x [2][1] = - Sine;
res.x [1][2] = Sine;
res.x [2][2] = Cosine;
return res;
};
Matrix RotateY (double Angle).
{.
Matrix res (1);
double Cosine = co (Angle);
double Sine = sin (Angle);
res.x [0][0] = Cosine;
res.x [2][0] = - Sine;
res.x [0][2] = Sine;
res.x [2][2] = Cosine;
return res;
};
Matrix RotateZ (double Angle).
{.
Matrix res (1);
double Cosine = co (Angle);
double Sine = sin (Angle);
res.x [0][0] = Cosine;
res.x [1][0] = - Sine;
res.x [0][1] = Sine;
res.x [1][1] = Cosine;
return res;
};
Matrix Rotate (const Vector& axis, double angle).
{.
Matrix res (1);
double Cosine = co (angle);
double Sine = sin (angle);
res.x [0][0] = axis. x * axis. x + (1 — axis. x * axis. x) * Cosine;
res.x [0][1] = axis. x * axis. y * (1 — Cosine) + axis. z * Sine;
res.x [0][2] = axis. x * axis. z * (1 — Cosine) — axis. y * Sine;
res.x [0][3] = 0;
res.x [1][0] = axis. x * axis. y * (1 — Cosine) — axis. z * Sine;
res.x [1][1] = axis. y * axis. y + (1 — axis. y * axis. y) * Cosine;
res.x [1][2] = axis. y * axis. z * (1 — Cosine) + axis. x * Sine;
res.x [1][3] = 0;
res.x [2][0] = axis. x * axis. z * (1 — Cosine) + axis. y * Sine;
res.x [2][1] = axis. y * axis. z * (1 — Cosine) — axis. x * Sine;
res.x [2][2] = axis. z * axis. z + (1 — axis. z * axis. z) * Cosine;
res.x [2][3] = 0;
res.x [3][0] = 0;
res.x [3][1] = 0;
res.x [3][2] = 0;
res.x [3][3] = 1;
return res;
};
Matrix MirrorX ().
{.
Matrix res (1);
res.x [0][0] = -1;
return res;
};
Matrix MirrorY ().
{.
Matrix res (1);
res.x [1][1] = -1;
return res;
};
Matrix MirrorZ ().
{.
Matrix res (1);
res.x [2][2] = -1;
return res;
}.
В наступній бібліотеці реалізували роботу з тривимірними об'єктами: межею, графічним об'єктом і простором. Реалізовано такі можливості:
поворот об'єктів навколо координатних осей;
зеркальное відображення об'єктів стосовно координатным осях;
центральное і паралельне проектування;
масштабирование об'єктів;
удаление невидимих поверхонь;
перемещение об'єктів у просторі.
//Файл 3dworks.h.
#ifndef __3DWORKS__#define __3DWORKS__#include.
#include.
#include «vector.h «.
#include «matrix.h «.
#define OneSd 0.
#define TwoSds 1.
#define MaxPoints 10.
#define MaxFacets 10.
#define MaxObjects 10.
class Polygon.
{.
public:
int PointNumber;
Vector * Point;
Vector Normal;
Vector Center;
int Color;
int TwoSides;
Polygon () {};
Polygon (Vector *, int, int, int);
void Draw (const Vector&);
void Move (const Vector&);
void Rotate (double, double, double);
void PolyScale (const Vector&);
void PolyMirrorX ();
void PolyMirrorY ();
void PolyMirrorZ ();
};
class GrObject.
{.
public:
int FacetNumber;
Polygon * Facet;
Vector Coords;
GrObject () {};
GrObject (Polygon *, int, const Vector&);
void Move (const Vector&);
void Rotate (double, double, double);
void ObjScale (const Vector&);
void ObjMirrorX ();
void ObjMirrorY ();
void ObjMirrorZ ();
};
struct BSPNode.
{.
Polygon * Poly;
double d;
BSPNode * Left;
BSPNode * Right;
};
class Space.
{.
public:
int ObjectNumber;
GrObject * Object [MaxObjects];
Space () { ObjectNumber = 0; };
Space (GrObject *, int);
void Add (GrObject *);
void Draw (const Vector&);
};
int IsVisible (const Polygon&, const Vector&);
void DrawBSPTree (BSPNode *, const Vector&);
#endif.
//——————————————————————————————————————.
//Файл 3dworks.cpp.
#include «3dworks.h «// Polygon «p.s methodsPolygon: Polygon (Vector * PointArr, int PointNum, int Col, int TS){ if (PointNum Tree -> d) {.
if (Tree -> Right ≠ NULL) DrawBSPTree (Tree -> Right, PrCntr);
Tree -> Poly -> Draw (PrCntr);
if (Tree -> Left ≠ NULL) DrawBSPTree (Tree -> Left, PrCntr);
}.
else {.
if (Tree -> Left ≠ NULL) DrawBSPTree (Tree -> Left, PrCntr);
Tree -> Poly -> Draw (PrCntr);
if (Tree -> Right ≠ NULL) DrawBSPTree (Tree -> Right, PrCntr);
}.
}.
Далее представлена демонстраційна програма, що виконує всі перелічені вище операції з тетраэдром.
//Файл 3dgame.cpp.
#include #include #include.
#include.
#include.
#include.
#include «3dworks.h «.
void DrawObject (GrObject* Obj, const Vector& v).
{.
for (int і = 0; і < Obj->FacetNumber; і++).
if (IsVisible (Obj->Facet[i], v)) Obj->Facet[i]. Draw (v);
}.
main ().
{.
Vector Poly1[3], Poly2[3], Poly3[3], Poly4[3];
Polygon O[4];
Vector A (-50, 0, 0),.
B (0, 0, 50),.
З (50, 0, 0),.
D (0, 100, 0),.
PrCenter (0, 0, 1000);
Poly1[0] = A; Poly2[0] = B;
Poly1[1] = D; Poly2[1] = D;
Poly1[2] = B; Poly2[2] = З;
Poly3[0] = З; Poly4[0] = З;
Poly3[1] = A; Poly4[1] = D;
Poly3[2] = B; Poly4[2] = A;
Polygon * P1 = new Polygon (Poly1, 3, 11, OneSd);
Polygon * P2 = new Polygon (Poly2, 3, 12, OneSd);
Polygon * P3 = new Polygon (Poly3, 3, 13, OneSd);
Polygon * P4 = new Polygon (Poly4, 3, 14, OneSd);
O[0] = *P1; O[1] = *P2;
O[2] = *P3; O[3] = *P4;
delete P1; delete P2;
delete P3; delete P4;
GrObject * Obj = new GrObject (O, 4, Vector (0));
double fi = 0.1, psi = 0.1, step = 0.1;
int ch = 0, Page = 3;
int driver = DETECT, mode, res;
initgraph (&driver, &mode, «»);
if ((res = graphresult ()) ≠ grOk) {.
printf («nGraphics error: %sn », grapherrormsg (res));
exit (1);
}.
setgraphmode (1);
DrawObject (Obj, PrCenter);
do {.
setactivepage (Page % 2);
clearviewport ();
if (kbhit ()).
{.
switch (ch = getch ()) {.
case «+ »: Obj->ObjScale ((1.1,1.1,1.1)); break;
case «- «: Obj->ObjScale ((0.9,0.9,0.9)); break;
case «x »: Obj->ObjMirrorX (); break;
case «y »: Obj->ObjMirrorY (); break;
case «z »: Obj->ObjMirrorZ (); break;
};
if (ch == 0).
{.
switch (ch = getch ()) {.
case 72: fi -= step; break;
case 80: fi += step; break;
case 75: psi += step; break;
case 77: psi -= step; break;
};
};
};
Obj->Rotate (fi, psi, 0);
DrawObject (Obj, PrCenter);
setvisualpage (Page++ % 2);
if (fi == 0 && psi == 0) while (!kbhit ());
} while (ch ≠ 27);
delete Obj;
closegraph ();
}.