Jump to content
  • Advertisement
dud3

3D 360 degrees rotation around x axis

Recommended Posts

How do we rotate the camera around x axis 360 degrees, without having the strange effect as in my video below? 

Mine behaves exactly the same way spherical coordinates would, I'm using euler angles.

Tried googling, but couldn't find a proper answer, guessing I don't know what exactly to google for, googled 'rotate 360 around x axis', got no proper answers.

 

References:

Code: https://pastebin.com/Hcshj3FQ

The video shows the difference between blender and my rotation:

 

Edited by dud3

Share this post


Link to post
Share on other sites
Advertisement

I would suggest using a parametrization of rotations that doesn't have a region where things get wacky. Either orthogonal matrices or quaternions would do.

 

Share this post


Link to post
Share on other sites

I think I'm stuck, I'm just trying to achieve the same rotation around the x axis as in blender.

The video shows the difference between blender and my rotation:

 

Edited by dud3

Share this post


Link to post
Share on other sites

You should have a notion of what the current attitude of your object is (i.e., the rotation that brings it from its initial position to its current position). When the mouse is clicked you create a new rotation, which depends only on the point where the mouse was initially clicked and its current position (perhaps just depends on the vector between those). While the mouse button is down, you display the object as having attitude (current_attitude * mouse_rotation). When the mouse button is released, you bake the mouse rotation into the attitude (`current_attitude *= mouse_rotation').

In the paragraph above I have used multiplicative notation to represent composition of rotations. Composition of rotations is hard if you are using Euler angles. But if you are using matrices or quaternions, it literally is a multiplication (be careful to get the order right, because it matters).

 

Edited by alvaro

Share this post


Link to post
Share on other sites

This is the current code, under dragTPSInput(...):
 

#pragma once

#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>

#include "InputHandler.h"
#include "Vector2D.h"

class Camera 
{
public:

	glm::vec3 m_position;
	
	glm::vec3 m_front;
	glm::vec3 m_up;
	glm::vec3 m_right;

	glm::vec3 m_worldup;

	float m_yaw;
	float m_pitch;

	float m_zoom;

	bool m_enableInput;

	// Mouse
	float m_mouseSensitivity;

	enum class direction { in, out, right, left };

	Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), 
		glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), 
		float yaw = -90.0f,
		float pitch = 0.0,
		float zoom = 1.0f,
		float mouseSensitivity = 0.05f) :
		m_front(glm::vec3(0.0f, 0.0f, -1.0f)), 
		m_enableInput(false)
	{
		m_position = position;

		m_yaw = yaw;
		m_pitch = pitch;

		m_worldup = up;

		m_zoom = zoom;
		m_mouseSensitivity = mouseSensitivity;

		updateCameraVectors();
	}

	void lookAt()
	{
	}

	void move(direction d)
	{
		if (d == direction::in)
			m_position -= m_front;
		
		if (d == direction::out)
			m_position += m_front;

		if(d == direction::right)
			m_position += glm::normalize(glm::cross(m_front, m_up)) * m_mouseSensitivity;

		if(d == direction::left)
			m_position -= glm::normalize(glm::cross(m_front, m_up)) * m_mouseSensitivity;
	}
	
	void rotate()
	{
	}

	void zoom()
	{
	}

	void scrollInput()
	{
	}

	void keyboardInput()
	{
		// todo: give the user ability to adjust input keys

		if (_inHandler->onKeyDown(SDL_SCANCODE_W)) {
			move(direction::in);
		}
		if (_inHandler->onKeyDown(SDL_SCANCODE_S)) {
			move(direction::out);
		}
		if (_inHandler->onKeyDown(SDL_SCANCODE_D)) {
			move(direction::right);
		}
		if (_inHandler->onKeyDown(SDL_SCANCODE_A)) {
			move(direction::left);
		}
	}

	void dragFPSInput(Vector2D* mouseMoveDiff, bool constrainPitch = true)
	{
		m_yaw += mouseMoveDiff->getX(); // offsetx
		m_pitch += -(mouseMoveDiff->getY()); // offsety

		// Make sure that when pitch is out of bounds, screen doesn't get flipped
		if (constrainPitch)
		{
			if (m_pitch > 89.0f)
				m_pitch = 89.0f;
			if (m_pitch < -89.0f)
				m_pitch = -89.0f;
		}

		// Update Front, Right and Up Vectors using the updated Eular angles
		updateCameraVectors();
	}

	void dragTPSInput(Vector2D* mouseMoveDiff)
	{
		// m_position = glm::rotate(m_position, -mouseMoveDiff->getY() * m_mouseSensitivity, glm::vec3(1, 0, 0));
		// m_position = glm::rotate(m_position, -mouseMoveDiff->getX() * m_mouseSensitivity, glm::vec3(0, 1, 0));

		glm::quat rot = glm::angleAxis(glm::radians(-mouseMoveDiff->getY()), glm::vec3(1, 0, 0));
		rot = rot * glm::angleAxis(glm::radians(-mouseMoveDiff->getX()), glm::vec3(0, 1, 0));

		glm::mat4 rotMatrix = glm::mat4_cast(rot);

		glm::vec4 pos = glm::vec4(m_position.x, m_position.y, m_position.z, 1.0f);

		pos = rotMatrix * pos;

		m_position.x = pos.x;
		m_position.y = pos.y;
		m_position.z = pos.z;

		updateCameraVectors();
	}

	void onInput(bool drag = true, bool scroll = true, bool keyboard = false)
	{
		if (drag)
			if (_inHandler->getMouseButtonState(_inHandler->mouse_buttons::LEFT))
				if(_inHandler->isMouseMovig())
					dragTPSInput(_inHandler->getMouseMoveDiff());

		if (scroll)
			scrollInput();

		if (keyboard)
			keyboardInput();
	}

	// Returns the view matrix calculated using Eular Angles and the LookAt Matrix
	glm::mat4 getViewMatrix()
	{
		glm::vec3 pos = glm::vec3(m_position.x, m_position.y, m_position.z);
		return glm::lookAt(pos, m_front, m_up);
	}

private:
	void updateCameraVectors()
	{
		// Calculate the new Front vector
		glm::vec3 front;
		front.x = cos(glm::radians(m_yaw)) * cos(glm::radians(m_pitch));
		front.y = sin(glm::radians(m_pitch));
		front.z = sin(glm::radians(m_yaw)) * cos(glm::radians(m_pitch));

		m_front = glm::normalize(front);

		// Also re-calculate the Right and Up vector
		// Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
		m_right = glm::normalize(glm::cross(m_front, m_worldup)); 
		
		m_up = glm::normalize(glm::cross(m_right, m_front));
	}

	InputHandler* _inHandler = TheInputHandler::Instance();
};

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!