Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

Centering a Ball on the Screen

Started by Josheir Jul 13, 2019 at 3:11 PM 17 replies 3.9k views
Original Post
Josheir
Josheir

I had a question earlier, but I have another question about something said in the post. Once again, here is the image of the rotation being wrong because the ball is not staying centered on the screen.

https://www.youtube.com/watch?v=ksNt3W_p5u8

I asked how do I keep the ball on the center of the screen. Here was the response:

Quote

Anyway, there are multiple ways you could get the behavior in that video. For example, you could transform an appropriate offset by the sphere's model/world transform to yield a camera position in world space, and then use a 'look at' transform to place the camera at that position and aim it at the sphere.

I an interested in all the ways to do this, and I 'm not understanding what this means, exactly. When I try to interchange World space and Camera space (use the same values for camera and translate) the ball isn't centered. Even when the camera is inverted.

Here's what it does:

https://www.youtube.com/watch?v=yCEwvnFEaRM

EDIT: the camera uses lookAt.

_WeirdCat_
_WeirdCat_

Dont know the api and what means lookat but i assume that you have a point where camera looks at so:

vec3 bdir = normalize( lookatpoint-campos);

vec3 ballpos = campos + somedistancefrom_camera*bdir;

Zakwayda
Zakwayda
52 minutes ago, Josheir said:

I asked how do I keep the ball on the center of the screen. Here was the response:

I think that particular suggestion was from me, but I made some other suggestions later in the thread that I think were probably more relevant and/or would be easier to implement.

I think there are some conceptual issues at play here regarding the basics of transforms, what they mean, and how to manage them. I think in the last thread I and others tried to provide an overview of the three types of transforms in a simple scene (projection, view, and world) and how they relate to each other. Although you might get lucky and stumble on a solution, I think solving this problem will more or less require coming to grips with some of the higher-level concepts we were talking about in the other thread.

I remember that one of the points of confusion was what behavior you wanted exactly. You posted a video that I think you said represented the desired behavior, in which the target object (a humanoid character in the video) rotated in world space, while the camera remained fixed with respect to the target object. However, you've also said this is a golf-like game, for which I'd expect the target object (the ball) not to rotate, and for the camera to rotate around the target. Can you clarify what behavior you want? Do you really want the ball to rotate? Could you post another (or the same) example video for reference?

Meanwhile, I think the easiest solutions available to you would probably be based on a 'look at' function. I think a good first step would just be to successfully use a 'look at' function to place the camera at an arbitrary position and have it aim at the ball. Once you have that working, the problem reduces to choosing an appropriate camera position, as discussed in the other thread. Once you have the basic 'look at' camera working, maybe we can help you in computing the camera position to give you the behavior you're after.

Alberth
Alberth
1 hour ago, Josheir said:

I an interested in all the ways to do this, and I 'm not understanding what this means, exactly. When I try to interchange World space and Camera space (use the same values for camera and translate) the ball isn't centered.

As far as I understand it, you need to compute the position of the ball in the world, and compute a camera position from that.

That is different from "normal" where you are at some (camera) position in the world, and look around. The latter is what "lookAt" does, it rotates the camera towards the lookAt point, the camera doesn't move as a result of the lookAt call.

Alternatively, you could always move the world such that the ball ends up at a fixed point in the world, say (0, 0, 0), and setup the camera somewhat away from that position.

Josheir
Josheir
7 minutes ago, Alberth said:

Alternatively, you could always move the world such that the ball ends up at a fixed point in the world, say (0, 0, 0), and setup the camera somewhat away from that position. 

I think I know what you mean, and I had this working but when I was using the barycentric equation (to make the ball collide with the terrain's height) the ball was interacting with the terrain not where the ball was but where the ball would be located with the rotation!

Josheir
Josheir
1 hour ago, _WeirdCat_ said:

Dont know the api and what means lookat but i assume that you have a point where camera looks at so:

vec3 bdir = normalize( lookatpoint-campos);

vec3 ballpos = campos + somedistancefrom_camera*bdir;

Something like this is what I was looking for, not a lot of theory, however theory isn't bad. I hope this works, how is somedistancefrom_camera determined. It's a vector?


Josheir

Zakwayda
Zakwayda
1 minute ago, Josheir said:

Something like this is what I was looking for, not a lot of theory, however theory isn't bad. I hope this works, how is somedistancefrom_camera determined. It's a vector?

That solution doesn't look right to me because it appears to compute the ball position from a known camera position, whereas it seems what you want is to compute the camera position from (perhaps among other things) a known ball position. Obviously I don't know for sure that it's not what you want, and you can always try it, but it doesn't seem consistent with what's been discussed elsewhere in this and your other thread. (For what it's worth, 'somedistancefrom_camera' would almost certainly be a scalar here. Distances are usually scalars, and a scalar would make the most sense in that particular example.)

I feel like in this and the other thread we're sort of avoiding talking about the actual problem and just sort of casting about for solutions randomly. To be sure, sometimes one can find a solution that way :) But if you find that _WeirdCat_'s suggestion doesn't give you what you want, I'd strongly suggest backing up a bit and trying to get a higher-level view of things.

I maintain that what you want to do is compute an appropriate camera position, and then use a 'look at' function to place the camera at that position and aim it at the ball. Once you have that working, the only task will be to compute an appropriate camera position, which I'm sure we can help you with. But I think we have to clear some initial hurdles first and get some fundamentals in place.

Lastly, if you find yourself still needing a solution for this, I again suggest clarifying what behavior you want (e.g. ball rotates and camera is fixed, or ball is fixed and camera rotates), and perhaps posting a video showing the desired behavior. (I know you posted an example video before, but I think further clarification would be useful.)

Josheir
Josheir

What's happening here :


vec3 ballpos = campos + somedistancefrom_camera*bdir;  

Hoe does it work that a vector is multiplied by a scalar, what is this going to do? A vector has three values and a scalar has only one? And where do I take this distance value from?

Green_Baron
Green_Baron
8 minutes ago, Josheir said:

What's happening here :



vec3 ballpos = campos + somedistancefrom_camera*bdir;  

Hoe does it work that a vector is multiplied by a scalar, what is this going to do? A vector has three values and a scalar has only one? And where do I take this distance value from?

???

Element wise multiplication, results in a new vector. These are the very basics you must know, or any attempt to help you will fail. Sorry for being so blunt ...

https://learnopengl.com/Getting-started/Transformations


Alberth
Alberth

vector multiplied by a scalar means you apply the vector that many times, ie multiply each element of the vector by the scalar, commonly known as elementwise multiplication, as the green baron said.

"somedistance" is such that it looks good I think. If you pick 0, the camera is in the ball, which could be nice, but likely not what you want. If you pick a larger number, the camera moves away from the ball, letting you choose between a ball of screen-filling size, or anything smaller, with infinity being less than a pixel in size.

Josheir
Josheir

We have solved my problem in another thread but I'm still interested in this approach (and the OpenGL camera in general.) The code above is implemented as:


			vec3 bdir = normalize(c_mycamera.front - c_mycamera.position);
			bdir.x = bdir.x * 1.2;
			bdir.y = bdir.y * 1.2;
			bdir.z = bdir.z * 1.2;
			vec3 ballpos = c_mycamera.position  +bdir;
			ball = glm::translate (ball, ballpos);

and here's a video with the same wrong unchanged behavior:

https://youtu.be/sA2bWb3SWz8

Why is it still rotating with the terrain, can we make this work too?

Thank you,

Josheir

P.S. I'll add the video of the other working code soon!

Green_Baron
Green_Baron

For reference, code of a working orbiting camera.


1.) Initialize camera vectors on setup:

m_target is the position of the ball, translated to for example 0/0/0

m_position is the initial camera position, set to for example m_target - vec3{0,0,5}


glm::vec3 direction{ m_target - m_position };
m_distance = glm::length( m_target - m_position );
m_yaw = glm::degres( std::atan2( -direction.x, direction.z ) );
m_pitch = glm::degrees( std::atan2( direction.y, std::sqrt( ( direction.x * direction.x) + ( direction.y * direction.y ) ) ) );

I use degrees because intuitive and makes more sense on display.

2.) In your render loop, after having processed input:


float yaw{ -glm::radians( m_yaw ) };
float pitch{ -glm::radians( m_pitch ) };
// Calculate the camera position on the sphere around the target
m_position = glm::dvec3{ m_distance * std::sin( yaw ) * std::cos( pitch ),
						 m_distance * std::sin( pitch ),
						-m_distance * std::cos( yaw ) * std::cos( pitch ) };
// Normalization not necessarily needed here. But later when buidling the frustum.
m_front = glm::normalize( m_target - m_position );
// conversion to float because precision isn't needed here
m_viewMatrix = glm::lookAt( glm::vec3{ m_position }, glm::vec3{ m_target }, m_up );
// Also re-calculate the right vector. Normalize for later use
m_right = glm::normalize( glm::cross( m_front, m_up ) );
m_projectionViewMatrix = m_perspectiveProjectionMatrix * m_viewMatrix;

Code for an orbiting camera. Projection matrix is only calculated when viewport or near/far planes change.


If you want to change the distance for example with the mouse wheel, you must recalc it in the loop. You will want to use pitch and yaw from the ball, so that the camera is following it. Also, maybe you will want to limit camera movement to the y/z plane, which should be trivial now that you have read the linear algebra things ?

No guarantee ;-).


Edit: looks like you have deleted the video and thus invalidated my post. The camera in the video was still freely turning and not locked to the ball.

Josheir
Josheir

I just switched it from private to public, tell me if it fails again please.


Green_Baron
Green_Baron

That's a different video than the one i reacted upon in my post.

Is your problem solved ? Because it seems that it is the camera that stays in position in relation to the terrain and the ball moves around as the camera turns. I thought you wanted the camera moving around the ball. Seems i misunderstood ...

Zakwayda
Zakwayda
36 minutes ago, Josheir said:

I just switched it from private to public, tell me if it fails again please.

Well, if that's what you were after, then I guess I was wrong all along about what behavior you wanted :| I thought at one point you mentioned it was a golf or golf-like game, so I was envisioning a ball that was stationary (like on a tee or whatever) while the camera rotated around it to determine the direction in which it would be hit. In that video though, you basically have first-person controls, with a ball that's being 'carried around', as it were. (It also doesn't look like it's actually centered, but maybe that's incidental.) Anyway, maybe I just misunderstood.

Josheir
Josheir

Instead of the camera rotating around, the world just rotates instead. It is my first project in OpenGL, it's what I envisioned. Thanks for your help! Yes, that's my current problem and it's solved.

Thanks,

Josheir


Thanks for the orbital camera, really great!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.