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 (ux + vx, uy + vy, uz + vz);
)
inline Vector operator - (const Vector & u, const Vector & v)
(
return Vector (ux - vx, uy - vy, uz - vz);
)
inline Vector operator * (const Vector & u, const Vector & v)
(
return Vector (ux * vx, uy * vy, uz * vz);
)
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 (ux/vx, uy/vy, uz/vz);
)
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 i = 0; i <4; i + +) for (j = 0; j <4; j + +) x [i] [j] = (i == j)? v: 0.0; x [3] [3] = 1;) void Matrix:: Invert ()
(
Matrix Out (1);
for (int i = 0; i <4; i + +) (
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! = i) (
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 i = 0; i <4; i + +)
for (j = 0; j <4; j + +)
if (i! = 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 i = 0; i <4; i + +)
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 i = 0; i <4; i + +)
for (j = 0; j <4; j + +)
x [i] [j] -= A.x [i] [j];
return * this;
)
Matrix & Matrix:: operator *= (double v)
(
int j;
for (int i = 0; i <4; i + +)
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 i = 0; i <4; i + +)
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 i = 0; i <4; i + +)
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 i = 0; i <4; i + +)
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 i = 0; i <4; i + +)
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 i = 0; i <4; i + +)
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 = vx * Mx [0] [0] + vy * Mx [1] [0] + vz * Mx [2] [0] + Mx [3] [0];
res.y = vx * Mx [0] [1] + vy * Mx [1] [1] + vz * Mx [2] [1] + Mx [3] [1];
res.z = vx * Mx [0] [2] + vy * Mx [1] [2] + vz * Mx [2] [2] + Mx [3] [2];
double denom = vx * Mx [0] [3] + vy * Mx [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 = cos (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 = cos (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 = cos (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 = cos (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'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 i = 0; i FacetNumber; i + +)
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),
C (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] = C;
Poly3 [0] = C; Poly4 [0] = C;
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 ();
)