From 594138cf96a2411e7e99ab7ac5a9fdd61fa42674 Mon Sep 17 00:00:00 2001 From: erikgoe Date: Sun, 24 Jan 2021 21:41:23 +0100 Subject: [PATCH] Make final polishing (challenge end) --- terminalDonut.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/terminalDonut.cpp b/terminalDonut.cpp index d8ee880..9338edd 100644 --- a/terminalDonut.cpp +++ b/terminalDonut.cpp @@ -16,6 +16,7 @@ struct Vector3 { Vector3 operator*( const float &factor ) const { return Vector3{ x * factor, y * factor, z * factor }; } float dot_product( const Vector3 &other ) const { return x * other.x + y * other.y + z * other.z; } + float length() const { return std::sqrt( this->dot_product( *this ) ); } }; struct Matrix3 { @@ -46,16 +47,16 @@ struct Matrix3 { int main() { // Create a simple ring in the xy-plane - const size_t RING_SECTIONS = 32; + const size_t RING_SECTIONS = 64; Vector3 basic_ring[RING_SECTIONS]; for ( size_t i = 0; i < RING_SECTIONS; i++ ) basic_ring[i] = Vector3::in_xy_circle( i * M_PI * 2 / RING_SECTIONS ); // Create the torus - const size_t TORUS_SECTIONS = 128; + const size_t TORUS_SECTIONS = 256; Vector3 torus[RING_SECTIONS * TORUS_SECTIONS]; Vector3 normals[RING_SECTIONS * TORUS_SECTIONS]; - Vector3 index = Vector3{ 2.5f, 0.f, 0.f }; + Vector3 index = Vector3{ 2.f, 0.f, 0.f }; for ( size_t i = 0; i < TORUS_SECTIONS; i++ ) { auto rotation = Matrix3::rotationAroundY( i * M_PI * 2 / TORUS_SECTIONS ); for ( size_t j = 0; j < RING_SECTIONS; j++ ) { @@ -71,13 +72,15 @@ int main() { float render_buffer[BUFFER_SIZE_X][BUFFER_SIZE_Y]; float z_buffer[BUFFER_SIZE_X][BUFFER_SIZE_Y]; Vector3 center = Vector3{ 32.f, 32.f, 32.f }; - Vector3 light_dir = Vector3::in_xy_circle( -M_PI / 2.f ); + Vector3 light_dir = Vector3{ -0.4f, -1.f, 0.4f }; + light_dir = light_dir * ( 1.f / light_dir.length() ); float time = 0.f; // Main loop while ( running ) { - auto x_rotation = Matrix3::rotationAroundX( M_PI / 2.f * std::sin( time * 1.2 ) ); - auto y_rotation = Matrix3::rotationAroundY( M_PI / 2.f * std::sin( time + 1.2 ) ); + auto x_rotation = Matrix3::rotationAroundX( M_PI / 2.f * std::sin( time * 1.5 ) ); + auto y_rotation = Matrix3::rotationAroundY( M_PI / 2.f * std::sin( time * 1.5 + 1.5 ) ); + auto z_rotation = Matrix3::rotationAroundZ( M_PI / 2.f * std::sin( time + 1.5 ) ); // Clear buffer for ( size_t y = 0; y < BUFFER_SIZE_Y; y++ ) { for ( size_t x = 0; x < BUFFER_SIZE_X; x++ ) { @@ -88,15 +91,17 @@ int main() { // Rotate and project the torus for ( size_t i = 0; i < TORUS_SECTIONS * RING_SECTIONS; i++ ) { - auto final_position = y_rotation * ( x_rotation * torus[i] ); - auto final_normal = y_rotation * ( x_rotation * normals[i] ); - final_position = final_position * 6.f + center; // adjust position into viewport + auto final_position = z_rotation * ( y_rotation * ( x_rotation * torus[i] ) ); + auto final_normal = z_rotation * ( y_rotation * ( x_rotation * normals[i] ) ); + final_position = final_position * 8.f + center; // adjust position into viewport int x = static_cast( std::round( final_position.x ) ); int y = static_cast( std::round( final_position.y * character_ratio ) ); int z = static_cast( std::round( final_position.z ) ); - if ( z_buffer[x][y] + 0.1 < z ) { + if ( z_buffer[x][y] + 0.1f < z ) { render_buffer[x][y] = final_normal.dot_product( light_dir ); z_buffer[x][y] = final_position.z; + } else if ( std::abs( z_buffer[x][y] - z ) < 0.1f ) { + render_buffer[x][y] = ( render_buffer[x][y] + final_normal.dot_product( light_dir ) ) / 2.f; } } @@ -117,7 +122,7 @@ int main() { // Ensure ~60 FPS std::this_thread::sleep_for( std::chrono::milliseconds( 16 ) ); - time += 0.01; + time += 0.015; } return 0;