tBane Temat założony przez niniejszego użytkownika |
[SFML3.1 OpenGL] Poprawna Rotacja Sześcianu » 2026-10-19 20:43:05 Cześć Wam! :D Piszę sobie program w SFML3 i OpenGL, który ma renderować 3 sześciany. Na lewy przycisk można przesuwać sześciany, zaś na prawy je obracać. Chciałbym napisać taką funkcję, która pozwala chwycić i obrócić sześcian zgodnie z przesunięciem kursora - czyli dosłownie "złap i obróć". Niesty gdy obrócę sześcian o 180 stopni w osi Z to potem źle obraca w osi Y. Kiedyś ktoś wspominał na tym forum ten problem i go zlekceważyłem... No więc przepraszam - problem powrócił :P SFML3.1 OpenGL - Cubes void Model3D::handleEvent( const sf::Event & event ) { static sf::Vector2i offset( 0.0f, 0.0f ); static sf::Vector2i rotationOffset( 0.0f, 0.0f ); static sf::Vector2f startRotation = sf::Vector2f( _rx, _ry ); auto size = Main::render_window->getSize(); auto mouse = Main::cursor->_position; float aspect =( float )( size.x ) / size.y; float distance = 5.0f - _z; float halfHeight = distance * std::tan( 30.0f * 3.14159265f / 180.0f ); float halfWidth = halfHeight * aspect; float mouseX =( 2.0f * mouse.x / size.x - 1.0f ) * halfWidth; float mouseY =( 1.0f - 2.0f * mouse.y / size.y ) * halfHeight; if( scene->_hovered == this->shared_from_this() ) { if( const auto * mbp = event.getIf < sf::Event::MouseButtonPressed >(); mbp ) { scene->_pressed = this->shared_from_this(); if( mbp->button == sf::Mouse::Button::Left ) { offset.x = mouseX - _x; offset.y = mouseY - _y; } if( mbp->button == sf::Mouse::Button::Right ) { rotationOffset = Main::cursor->_position; startRotation = sf::Vector2f( _rx, _ry ); } } } if( scene->_pressed == this->shared_from_this() ) { if( sf::Mouse::isButtonPressed( sf::Mouse::Button::Left ) ) { _x = mouseX - offset.x; _y = mouseY - offset.y; } if( sf::Mouse::isButtonPressed( sf::Mouse::Button::Right ) ) { auto delta = Main::cursor->_position - rotationOffset; _ry = startRotation.y + delta.x * 0.5f; _rx = startRotation.x + delta.y * 0.5f; } } if( const auto * mbr = event.getIf < sf::Event::MouseButtonReleased >(); mbr ) { if( scene->_pressed == this->shared_from_this() ) scene->_pressed = nullptr; } }
void Mesh3D::draw( bool isHighlighted, float x, float y, float z, float rx, float ry, float rz ) { glPushMatrix(); glTranslatef( x, y, z ); glRotatef( rx, 1.f, 0.f, 0.f ); glRotatef( ry, 0.f, 1.f, 0.f ); glRotatef( rz, 0.f, 0.f, 1.f ); glEnable( GL_TEXTURE_2D ); ( isHighlighted ) ? glColor3f( 1.0f, 1.0f, 1.f ) : glColor3f( 0.75f, 0.75f, 0.75f ); glBindTexture( GL_TEXTURE_2D, _texture ? _texture->_texture->getNativeHandle() : 0 ); glBegin( GL_TRIANGLES ); for( auto & vertex: _vertices ) { glNormal3f( vertex._nx, vertex._ny, vertex._nz ); glTexCoord2f( vertex._u, 1.0f - vertex._v ); glVertex3f( vertex._x, vertex._y, vertex._z ); } glEnd(); glBindTexture( GL_TEXTURE_2D, 0 ); glPopMatrix(); }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2026-10-19 23:40:15 Trzeba zastosować kwaterniony: #pragma once
#include <array> #include <cmath>
struct Quaternion { float w = 1.f; float x = 0.f; float y = 0.f; float z = 0.f; Quaternion operator *( const Quaternion & q ) const { return { w * q.w - x * q.x - y * q.y - z * q.z, w * q.x + x * q.w + y * q.z - z * q.y, w * q.y - x * q.z + y * q.w + z * q.x, w * q.z + x * q.y - y * q.x + z * q.w }; } void normalize() { const float length = std::sqrt( w * w + x * x + y * y + z * z ); if( length > 0.f ) { w /= length; x /= length; y /= length; z /= length; } } std::array < float, 16 > matrix() const { return { 1.f - 2.f *( y * y + z * z ), 2.f *( x * y + w * z ), 2.f *( x * z - w * y ), 0.f, 2.f *( x * y - w * z ), 1.f - 2.f *( x * x + z * z ), 2.f *( y * z + w * x ), 0.f, 2.f *( x * z + w * y ), 2.f *( y * z - w * x ), 1.f - 2.f *( x * x + y * y ), 0.f, 0.f, 0.f, 0.f, 1.f }; } };
if( const auto * moved = event.getIf < sf::Event::MouseMoved >(); moved && sf::Mouse::isButtonPressed( sf::Mouse::Button::Right ) ) { const auto delta = moved->position - _lastRotationMouse; _lastRotationMouse = moved->position; const float dx = static_cast < float >( delta.x ); const float dy = static_cast < float >( delta.y ); const float length = std::hypot( dx, dy ); if( length > 0.f ) { constexpr float sensitivity = 0.5f; constexpr float toRadians = 3.14159265f / 180.f; const float halfAngle = length * sensitivity * toRadians * 0.5f; const float s = std::sin( halfAngle ) / length; const Quaternion deltaRotation { std::cos( halfAngle ), dy * s, dx * s, 0.f }; _rotation = deltaRotation * _rotation; _rotation.normalize(); } }
void Mesh3D::draw( bool isHighlighted, float x, float y, float z, const Quaternion & rotation ) { const auto matrix = rotation.matrix(); glMultMatrixf( matrix.data() ); |
|
| « 1 » |