Смекни!
smekni.com

Трехмерная графика Теория (стр. 2 из 2)

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 = 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 = 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 <graphics.h>

#include <stdlib.h>

#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 <= MaxPoints ) { PointNumber = PointNum; Point = PointArr; Color = Col; TwoSides = TS;

Normal = Normalize (

( Point [1] - Point [0] ) ^ ( Point [PointNumber-1] - Point [0] ));

Center = 0;

for ( int i = 0; i < PointNumber; i++ )

Center += Point[i];

Center /= PointNumber;

}

}

void Polygon :: Move ( const Vector& v )

{

Matrix m = Translate ( v );

for ( int i = 0; i < PointNumber; i++ )

Point[i] = m * Point[i];

Center = m * Center;

}

void Polygon :: Rotate ( double Alfa, double Beta, double Gamma )

{

Matrix m = RotateX ( Alfa ) * RotateY ( Beta ) * RotateZ ( Gamma );

for ( int i = 0; i < PointNumber; i++ )

Point[i] = m * Point[i];

Normal = m * Normal;

Center = m * Center;

}

void Polygon :: PolyScale ( const Vector& v )

{

Matrix m = Scale ( v );

for ( int i = 0; i < PointNumber; i++ )

Point[i] = m * Point[i];

Center = m * Center;

}

void Polygon :: PolyMirrorX ()

{

Matrix m = MirrorX();

for ( int i = 0; i < PointNumber; i++ )

Point[i] = m * Point[i];

Center = m * Center;

Normal = m * Normal;

}

void Polygon :: PolyMirrorY ()

{

Matrix m = MirrorY();

for ( int i = 0; i < PointNumber; i++ )

Point[i] = m * Point[i];

Center = m * Center;

Normal = m * Normal;

}

void Polygon :: PolyMirrorZ ()

{

Matrix m = MirrorZ();

for ( int i = 0; i < PointNumber; i++ )

Point[i] = m * Point[i];

Center = m * Center;

Normal = m * Normal;

}

void Polygon :: Draw ( const Vector& PrCenter )

{

int VisPoint[MaxPoints * 2], k = 0;

for ( int i = 0; i < PointNumber; i++ ) {

double Coeff = 1 / ( 1 - Point[i].z / PrCenter.z );

VisPoint[k++] = ( int ) Point[i].x * Coeff + 320;

VisPoint[k++] = ( int ) -Point[i].y * Coeff + 175;

}

setcolor ( Color );

setfillstyle ( 1, Color );

fillpoly ( PointNumber, VisPoint );

}

// GrObject's methods

GrObject :: GrObject ( Polygon * FacetArr, int FacetNum, const Vector& Crds )

{

if ( FacetNum <= MaxFacets )

{

FacetNumber = FacetNum;

Facet = FacetArr;

Coords = Crds;

}

}

void GrObject :: Move ( const Vector& v )

{

for ( int i = 0; i < FacetNumber; i++ )

Facet[i].Move ( v );

Coords = Translate ( v ) * Coords;

}

void GrObject :: Rotate ( double Alfa, double Beta, double Gamma )

{

for ( int i = 0; i < FacetNumber; i++ )

Facet[i].Rotate ( Alfa, Beta, Gamma );

Coords = RotateX ( Alfa ) * RotateY ( Beta ) * RotateZ ( Gamma ) * Coords;

}

void GrObject :: ObjScale ( const Vector& v )

{

for ( int i = 0; i < FacetNumber; i++ )

Facet[i].PolyScale ( v );

Coords = Scale ( v ) * Coords;

}

void GrObject :: ObjMirrorX ()

{

Matrix m = MirrorX();

for ( int i = 0; i < FacetNumber; i++ )

Facet[i].PolyMirrorX ();

Coords = m * Coords;

}

void GrObject :: ObjMirrorY ()

{

Matrix m = MirrorY();

for ( int i = 0; i < FacetNumber; i++ )

Facet[i].PolyMirrorY ();

Coords = m * Coords;

}

void GrObject :: ObjMirrorZ ()

{

Matrix m = MirrorZ();

for ( int i = 0; i < FacetNumber; i++ )

Facet[i].PolyMirrorZ ();

Coords = m * Coords;

}

// Space's methods

Space :: Space ( GrObject * Obj, int ObjectNum )

{

if ( ObjectNum <= MaxObjects )

{

ObjectNumber = ObjectNum;

for ( int i = 0; i < ObjectNumber; i++ )

Object[i] = &Obj[i];

};

}

void Space :: Add ( GrObject * Obj )

{

if ( ObjectNumber < MaxObjects ) Object [ObjectNumber++] = Obj;

}

void Space :: Draw ( const Vector& PrCenter )

{

}

// Other functions

int IsVisible ( const Polygon& Poly, const Vector& PrCenter )

{

return ( Poly.Normal & ( PrCenter - Poly.Point[0] )) < 0 || Poly.TwoSides;

}

void DrawBSPTree ( BSPNode * Tree, const Vector& PrCntr )

{

if (( Tree -> Poly -> Normal & PrCntr ) > 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 <dos.h>#include <graphics.h>#include <math.h>

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include "3dworks.h"

void DrawObject ( GrObject* Obj, const Vector& v )

{

for ( int i = 0; i < Obj->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 ( "&bsol;nGraphics error: %s&bsol;n", 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 ();

}