1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
#include <iostream>
#include <vector>
#include <utility>
#include <cmath>
#include <windows.h>
using namespace std;
const double PI = 4.0 * atan( 1.0 );
const double degToRad = PI / 180.0;
using matrix = vector< vector<double> >;
//======================================================================
struct Point
{
double x, y, z;
Point( double x = 0, double y = 0, double z = 0 ) : x( x ), y( y ), z( z ) {}
};
Point operator + ( const Point &a, const Point &b ){ return { a.x + b.x, a.y + b.y, a.z + b.z }; }
Point operator - ( const Point &a, const Point &b ){ return { a.x - b.x, a.y - b.y, a.z - b.z }; }
Point operator / ( const Point &a, double d ){ return { a.x / d, a.y / d, a.z / d }; }
Point operator * ( double d , const Point &a ){ return { d * a.x, d * a.y, d * a.z }; }
Point cross ( const Point &a, const Point &b ){ return { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x }; }
double dot ( const Point &a, const Point &b ){ return a.x * b.x + a.y * b.y + a.z * b.z; }
double normsq ( const Point &a ){ return dot( a, a ); }
double len ( const Point &a ){ return sqrt( normsq( a ) ); }
Point unit ( const Point &a ){ return a / len( a ); }
ostream & operator << ( ostream &out, const Point a ){ return out << a.x << " " << a.y << " " << a.z << " "; }
Point perspective( const Point &p, const Point &focus, double eye )
{
double f = ( p.z - focus.z ) / ( eye - focus.z );
return { focus.x + f * ( p.x - focus.x ), focus.y + f * ( p.y - focus.y ), p.z };
}
Point operator * ( const matrix &M, const Point &v )
{
return { M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z,
M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z,
M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z };
}
matrix operator * ( const matrix &M, const matrix &N )
{
matrix R( M.size(), vector<double>( N[0].size(), 0.0 ) );
for ( int i = 0; i < M.size(); i++ )
{
for ( int j = 0; j < N[0].size(); j++ )
{
for ( int k = 0; k < N.size(); k++ ) R[i][j] += M[i][k] * N[k][j];
}
}
return R;
}
//======================================================================
matrix rotationMatrix( const Point &axis, double radians ) // Rotation matrix from axis and angle
{
matrix result( 3, vector<double>( 3 ) );
Point n = unit( axis );
double cosA = cos( radians ), sinA = sin( radians ), cosA1 = 1.0 - cosA;
result[0][0] = cosA + n.x * n.x * cosA1;
result[0][1] = + n.x * n.y * cosA1 - n.z * sinA;
result[0][2] = + n.x * n.z * cosA1 + n.y * sinA;
result[1][0] = + n.y * n.x * cosA1 + n.z * sinA;
result[1][1] = cosA + n.y * n.y * cosA1;
result[1][2] = + n.y * n.z * cosA1 - n.x * sinA;
result[2][0] = + n.z * n.x * cosA1 - n.y * sinA;
result[2][1] = + n.z * n.y * cosA1 + n.x * sinA;
result[2][2] = cosA + n.z * n.z * cosA1;
return result;
}
//======================================================================
matrix rotationMatrix( const Point &EulerAngles ) // Rotation matrix from Euler angles
{
return rotationMatrix( { 0.0, 0.0, 1.0 }, EulerAngles.z )
* rotationMatrix( { 0.0, 1.0, 0.0 }, EulerAngles.y )
* rotationMatrix( { 1.0, 0.0, 0.0 }, EulerAngles.x );
}
//======================================================================
int main()
{
vector<Point> vertices = { { 200, 100, 0 }, { 300, 100, 0 }, { 300, 200, 0 }, { 200, 200, 0 },
{ 200, 100, 100 }, { 300, 100, 100 }, { 300, 200, 100 }, { 200, 200, 100 } };
vector<pair<int,int>> lines = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 },
{ 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } };
Point centre = { 250, 150, 50 };
Point focus = centre - Point{ 0, 0, 300 };
const double eye = 0.0;
HDC WindowHDC = GetDC( GetConsoleWindow() );
HPEN hpen = CreatePen( PS_SOLID, 1, RGB( 255, 0, 0 ) );
HBRUSH background = CreateSolidBrush( RGB( 0, 0, 0 ) );
double angley = 0.0;
do
{
SelectObject( WindowHDC, hpen );
for ( auto pr : lines )
{
matrix R = rotationMatrix( { 0.0, 1.0, 0.0 }, angley );
Point p = perspective( centre + R * ( vertices[pr.first ] - centre ), focus, eye );
Point q = perspective( centre + R * ( vertices[pr.second] - centre ), focus, eye );
MoveToEx( WindowHDC, p.x, p.y, nullptr );
LineTo ( WindowHDC, q.x, q.y );
}
Sleep(10);
RECT a; a.left=0, a.right=1000, a.top=0, a.bottom=1000;
FillRect( WindowHDC, &a, background );
angley += 1.0 * degToRad;
} while ( !( GetKeyState( VK_ESCAPE ) & 0x8000 ) ); //press escape for exit
}
| |