Weird vertical camera rotation

Started by
1 comment, last by FonzTech 8 years, 3 months ago

Hi at all! I'm playing and experimenting with OpenGL. I wanted to do a 3D camera, and this is the algorithm I used:

1) Store global mouse coordinates
2) Reset mouse position at the center of the screen
3) Increment horizontal and vertical camera directions by the variation of mouse coordinates (what others call "delta" mouse coordinates, computed from the difference of previous stored variables)
4) Compute X, Y and Z position using trigonometry, then pass to the glm::lookAt object.

The horizontal rotation it's OK, but the vertical one isn't. I think the problem is the gimbal lock... I've noticed that I used two axis for the horizontal one, and only one for the vertical one. So, as far as I know from a book I've read, I should use quartenions because it adds a fourth dimension. I've not yet studied quartenions at school (I am at the last year of high school)...

This is what happens:

2dqtyrr.gif

So, can you give me a quick solution or explanation to this problem?

Thanks in advance for any answer!

This is the code if you need it:


// Projection matrix : 45° Field of View, calculated aspect ratio, display range : 0.1 to 100 units
projection = glm::perspective(glm::radians(45.0f), Screen.aspectRatio, 0.1f, 65535.0f);

// Compute camera directions
float cpos[] = { 0.0f, 0.0f, 0.0f };
int mpos[] = { 0, 0 };

SDL_GetGlobalMouseState(&mpos[0], &mpos[1]);
SDL_WarpMouseGlobal(Screen.displayMode.w / 2, Screen.displayMode.h / 2);

Params.h_dir += (float)(mpos[0] - Screen.displayMode.w / 2) / Params.mousePrecision;
Params.v_dir += (float)(mpos[1] - Screen.displayMode.h / 2) / Params.mousePrecision;

cpos[0] = Position.x + cos(glm::radians(Params.h_dir)) * Params.distance;
cpos[1] = Position.y + sin(glm::radians(Params.v_dir)) * Params.distance;
cpos[2] = Position.z + sin(glm::radians(Params.h_dir)) * Params.distance;

// Camera matrix
view = glm::lookAt(
	glm::vec3(cpos[0], cpos[1], cpos[2]), // Camera is at computed position in World Space
	glm::vec3(Position.x, Position.y, Position.z), // and looks at the origin
	glm::vec3(0, 1, 0)  // Head is up (set to 0, -1, 0 to look upside-down)
);
Advertisement

You seem to map the mouse pointer position to a kind of inclination and azimuth pair of angles, using them together with a fix distance (radius) as spherical coordinates, convert that into cartesian coordinates, and transform that from object local into global space.

Accordingly to the formulas found e.g. at the end of the section here, your trigonometry isn't correct then.

Mmhh, Ok, I managed to do a nice third person camera with little changes:

cpos[0] = Position.x + cos(glm::radians(Params.v_dir)) * cos(glm::radians(Params.h_dir)) * Params.distance;
cpos[1] = Position.y + sin(glm::radians(Params.v_dir)) * Params.distance;
cpos[2] = Position.z + cos(glm::radians(Params.v_dir)) * sin(glm::radians(Params.h_dir)) * Params.distance;

I also restricted vertical rotation to stay between [-90, 90]. It's nice :)

This topic is closed to new replies.

Advertisement