M
MHBlacky
Guest
GM Version: GMS 1.4
Target Platform: All
Links: Basic First Person Camera Tutorial by The Sivart:
Summary
In this tutorial I will show you how to code a 3D camera rotation that can be done with the mouse. Compared to other 3D camera rotation codes with this one you can look anywhere from straight up in the air to straight down to the floor without any awkward changes in camera speed.
Tutorial
There are a lot of basic tutorials out there for 3D camera rotation. I've linked one in the header of this post. But one problem that they all have is that with the provided code it's impossible to look up or down completely in a 90 degree angle. But since you can do that in basically any other 3D game I'm sure you want to be able to do that in your game aswell. I was looking for a solution on the internet but didn't find one. If you know a post that already adresses this problem then this tutorial is unnecessary, my bad. But after some coding and testing I came up with this solution and wanted to share it with you guys.
First of this tutorial is about the camera rotation itself so I won't go into detail about setting up the views, the movement and all the other stuff needed for a functional 3D game. Also for simplicity reasons we assume that we're doing a first person camera. The provded steps also work for 3rd person cameras of course.
So this is what the usual 3D camera code looks like:
x,y and z are the coordinates where the camera is placed. cam_x, cam_y and cam_z are the coordinates of the point the camera is looking at. This point - let's call it CP - changes as we move the mouse. With the commands
cam_x = x + lengthdir_x(100,direction);
cam_y = y + lengthdir_y(100,direction);
cam_z = 10 + pitch;
we basically define a cylinder with a radius of 100 and a height of +-90 (because pitch goes from -90 to 90 degrees) around the player. This cylinder is a model for all the coordinats CP can have. And this leads to the basic problem: A correct camera movement should not work with a cylindric model. That's also the reason we can't look up and down correctly because the cylinder is not infinitely high and if it was then the camera sensitivity would be really weird. It's difficult for me to describe but believe me, you don't want that!
The solution: We use a sphere as model for our CP not a cylinder. If CP moves on a spheric surface we can look up and down correctly without any change to the mouse sensitivity. And that's how we do it:
For the cylinder "cam_x = x + lengthdir_x(100,direction);" and "cam_y = y + lengthdir_y(100,direction);" define the circular base and "cam_z = 10 + pitch;" the height. If we want to reshape that into a sphere we have to change cam_x and cam_y dynamically as a function of the height (pitch) of our sphere. The picture compares the spherical with the cylindrical model and should clarify what I mean:
So in order to change cam_x and cam_y dynamically we use the circle function f(x) = sqrt( r ²- x² ) with r being the radius of the circle:
With this code you should have a perfect camera movement over the whole pitch range.
If there's a built-in way to da that I feel stupid for posting this xD
Still hope it was helpful
Target Platform: All
Links: Basic First Person Camera Tutorial by The Sivart:
Summary
In this tutorial I will show you how to code a 3D camera rotation that can be done with the mouse. Compared to other 3D camera rotation codes with this one you can look anywhere from straight up in the air to straight down to the floor without any awkward changes in camera speed.
Tutorial
There are a lot of basic tutorials out there for 3D camera rotation. I've linked one in the header of this post. But one problem that they all have is that with the provided code it's impossible to look up or down completely in a 90 degree angle. But since you can do that in basically any other 3D game I'm sure you want to be able to do that in your game aswell. I was looking for a solution on the internet but didn't find one. If you know a post that already adresses this problem then this tutorial is unnecessary, my bad. But after some coding and testing I came up with this solution and wanted to share it with you guys.
First of this tutorial is about the camera rotation itself so I won't go into detail about setting up the views, the movement and all the other stuff needed for a functional 3D game. Also for simplicity reasons we assume that we're doing a first person camera. The provded steps also work for 3rd person cameras of course.
So this is what the usual 3D camera code looks like:
Code:
direction -= (display_mouse_get_x() - (display_get_width()/2));
pitch -= (display_mouse_get_y() - (display_get_height()/2));
pitch = clamp(pitch, -90, 90);
cam_x = x + lengthdir_x(100,direction);
cam_y = y + lengthdir_y(100,direction);
cam_z = 10 + pitch;
d3d_set_projection(x,y,z,cam_x,cam_y,cam_z,0,0,1);
cam_x = x + lengthdir_x(100,direction);
cam_y = y + lengthdir_y(100,direction);
cam_z = 10 + pitch;
we basically define a cylinder with a radius of 100 and a height of +-90 (because pitch goes from -90 to 90 degrees) around the player. This cylinder is a model for all the coordinats CP can have. And this leads to the basic problem: A correct camera movement should not work with a cylindric model. That's also the reason we can't look up and down correctly because the cylinder is not infinitely high and if it was then the camera sensitivity would be really weird. It's difficult for me to describe but believe me, you don't want that!
The solution: We use a sphere as model for our CP not a cylinder. If CP moves on a spheric surface we can look up and down correctly without any change to the mouse sensitivity. And that's how we do it:
For the cylinder "cam_x = x + lengthdir_x(100,direction);" and "cam_y = y + lengthdir_y(100,direction);" define the circular base and "cam_z = 10 + pitch;" the height. If we want to reshape that into a sphere we have to change cam_x and cam_y dynamically as a function of the height (pitch) of our sphere. The picture compares the spherical with the cylindrical model and should clarify what I mean:
So in order to change cam_x and cam_y dynamically we use the circle function f(x) = sqrt( r ²- x² ) with r being the radius of the circle:
Code:
var f_x = sqrt(power(91,2) - power(pitch,2)); // We define the radius as 91 so the sqrt doesn't get negative since pitch ranges from -90 to 90
cam_x = x + lengthdir_x(f_x, direction);
cam_y = y + lengthdir_y(f_x, direction);
cam_z = 10 + pitch;
If there's a built-in way to da that I feel stupid for posting this xD
Still hope it was helpful
Last edited by a moderator: