Rotation speed calculation - opengl

I am trying to make a game in space with Newtonian physics. I am trying to make an object (spaceship) increase its rotation speed when WASD keys are pressed. I used a vec3 to represent rotation speed for each axis. My problem is, how to calculate the rotation speed in respect to the coordinate system when I only know the speed I want in relation to my object (spaceship)?
In other words, my player is looking through the object. I want to go rotate left relative to him when he presses A, but I don't know how to calculate it in relation to the universe (coordinate system).

Related

implement 2D gravity and basic collision C++ and OpenGL Tile based side scroller game

I have some questions for correctly implementing a system that add gravity to my player while still detecting and correcting collision with the floor. I understand the basic math for the AABB and adding gravity vector to the players velocity vector then adding it to the position. For some reason when I try the player stops for the first few frames then eventually the velocity builds up to be more than the tile width and it goes through. I guess my real question is how to properly implement the gravity with the collision. Do I make gravity vector 0, 0 when it hits the floor or when I am just standing on the floor my collision detection will constantly move me out of the floor? I really don't know the flow of the logic with this situation.
Edit 1:
I am trying to make the simple engine myself to gain experience with programming. I kind of solved the one problem, I now can stop on the floor. My current logic is:
add gravity to velocity, check for collision, adjust the velocity by the offset of the collision, if any, add velocity to the position then set velocity to 0.
m_velocity += m_gravity;
glm::vec2 mtd = collideWithObject(objectVector);
m_velocity -= mtd;
m_position += m_velocity;
m_velocity.x = 0.0f;
m_velocity.y = 0.0f;
It works but I am not sure if that is the flow, I guess I just want to know what is the most common way to implement this.
For some reason when I try the player stops for the first few frames then eventually the velocity builds up to be more than the tile width and it goes through.
If you are applying physics in increments - such as once every frame - you must account for the infinite increments that exist between each of those points.
For a simple "plane collision", like your floor, don't test if your current AABB collides with the floor. Create the smallest AABB that includes your current AABB and the last AABB. If that box collides, you've collided with the plane.
as #MorphingDragon mentioned, you should consider Box2D, many games use Box2D.
For your question "Do I make gravity vector 0, 0 when it hits the floor or when I am just standing on the floor my collision detection will constantly move me out of the floor? I really don't know the flow of the logic with this situation.". I just assume you know Verlet integration, for calculate your new position, you don't need to change your gravity, [as you know, gravity is everywhere on earth, or you want to do a game in space, ;)] you just need to handle the collision detection logic as "when collision happens, just make the collision point satisfy my constraints", and your constraint should be "all point should not be placed under the floor, otherwise just move it and make it sit on the floor".
The collection detection and constraint solver theory should be very common in modern physical engine and easy to understand and implement.
Hope this help.
Thanks
An

Rotating Camera according to 3D Object's position

I'm using Opengl as the foundations for a small car simulation.
I've imported a model car and it drives around fine and the camera follows it. Unfortunately I can't seem to get the camera's position to move (or stay behind the car) when the car turns. It just rotates on the spot.
eg if the car turns left, the camera rotates to follow it but doesn't move to directly behind the car.
I've looked at these questions here and here but still can't seem to get it working.
This is how I calculate the position of the car (it just drives on the XZ plane for now):
velocity.x = sin(rotX_rad);
velocity.z = cos(rotX_rad);
globalPos.x + velocity.x*delta;
globalPos.z + velocity.z*delta;
glTranslatef(globalPos.x,globalPos.y,globalPos.z);
glRotatef(rotX, 0.0, 1.0, 0.0);
And this is currently how I have my lookAt function:
gluLookAt(camX+globalPos.x,
camY+globalPos.y,
camZ+globalPos.z,
lookX+globalPos.x+sin(rotX_rad),
lookY+globalPos.y+cos(rotX_rad),
lookZ+globalPos.z-cos(rotX_rad),
camNX, camNY, camNZ);
I would like the camera to be like this: (where Y is Z)
The way I see it, it should be:
camX + globalPos.x+ sin(rotX_rad)*(distFromCar),
camY,
camZ + globalPos.z- cos(rotX_rad)*(distFromCar),
but it behaves strangely....
What am I not doing?
Give this a shot, it makes sense in my head but it might not in reality :)
Ok, so we can represent your car's position and velocity as 2-element vectors (in the case of position it is a point, and in the case of velocity it is a true vector.)
Now that we have that, to calculate the position of the camera we can just take the negative of your velocity vector (this means just make all elements of the vector negative, yielding a vector of the same magnitude but exactly opposite direction) and add that vector to your car's position.
For example, say your car is at position (1,1) and your speed vector is (1,2). The negative speed vector would be (-1,-2) and the position of your camera would be (1,1) + (-1,-2) to be (0,-1). You will probably want to normalize the negative speed vector so that your camera stays a constant distance from the car, otherwise the faster you go the further the camera will get :)
Now that you have the camera's position, just call gluLookAt:
gluLookAt(camPos.x,camPos.y,camPos.z,carPos.x,carPos.y,carPos.z,0,1,0);
As you can see, we are passing in the camera's position (which we just calculated in the previous step) and telling the camera to look at the car. You may want to tweak some values (for example, have the camera be floating a few units off the ground, instead of directly behind the car, or maybe have the camera look at a point a few units above the car, etc.)
Let me know how this goes! Again, this is just something I thought might work for you, no guarantees that my math is right though :) But this should be faster and easier to understand than messing around with angles and such. One thing to keep in mind: this will not work if the car is completely stationary (no velocity vector)

Finding the angle of a coordinate inside a circle

Right down to business, basically I am making a small mini game which has characters running on top of a flat clock with the clock hand rotating around, the characters have to avoid it by jumping.
the part im struggling with is coding the collision, the clock hand is just a set model that is rotated applying matrices and for whatever reason box collision will not work.
So my theory is because i know the angle that the clock hand is currently being multiplied by, is there some mathematical way to calculate the angle of the player in relation to the centre point of the circle so that this can be checked against the clock hand angle?
Sure.
float angle = atan2(y_handle - y_center, x_handle - x_center);

Tracking circular mouse movement in OpenGL

I am working on a simple mesh viewer implementation in C++ with basic functionality such as translation, rotation, scaling.
I'm stuck with with implementing the rotation of the object along z-axis using the mouse. What I want to implement is the following:
Click and drag the mouse vertically (almost vertical will do, as I use a simple threshold to filter slight deviations along the horizontal axis) to rotate the object along y-axis (this part is done).
Click and drag the mouse horizontally just as described above to rotate the object along x-axis (this part is done too).
For z-axis rotation, I want to detect a circular (or along an arc) mouse movement. I'm stuck with this part, and don't know how to implement this.
For the above two, i just use atan2() to determine the angle of movement. But how do I detect circular movements?
The only way to deal with this is to have a delay between the user starting to make the motion and the object rotating:
When user clicks and begins to move the mouse you need to determine if its going to become a straight line movement, or a circular one. This will require a certain amount of data to be collected before that judgement can be made.
The most extreme case would be requiring the user to make one complete circle first, then the rotation begins (in reality you could do much better than this). Just how small you are able to cut this period down to will depend on a) how precise you dictate your users actions must be, and b) how good you are with pattern recognition algorithms.
To get you started heres an outline of an extremely poor algorithm:
On user click store the x and y coordinates.
Every 1/10 of a second store the new coordinates and process_for_pattern.
in process_for_pattern you're looking for:
A period where the x coordinates and the y coordinates regularly both increase, both decrease, or one increases and one decreases. Over time if this pattern changes such that either the x or the y begins to reverse whilst the other continues as it was, then at that moment you can be fairly sure you've got a circle.
This algorithm would require the user to draw a quarter circle before it was detected, and it does not account for size, direction, or largely irregular movements.
If you really want to continue with this method you can get a much better algorithm, but you might want to reconsider your control method.
Perhaps, you should define a screen region (e.g. at window boundaries), which, when was clicked, will initiate arc movement - or use some other modifier, a button or whatever.
Then at a mouse click you capture the coordinates and center of rotation (mesh axis) in 2D screen space. This gets you a vector (mesh center, button down pos)
On every mouse move you calculate a new vector (mesh center, mouse pos) and the angle between the two vectors is the angle of rotation.
I don't think it works like that...
You could convert mouse wheel rotation to z-axis, or use quaternion camera orientation, which is able to rotate along every axis almost intuitively...
The opposite is true for quarternion camera: if one tries to rotate the mesh along a straight line, the mesh appears to rotate slightly around some other weird axis -- and to compensate that, one intuitively tries to follow some slightly curved trajectory.
It's not exactly what you want, but should come close enough.
Choose a circular region within which your movements numbered 1 and 2 work as described (in the picture this would be some region that is smaller than the red circle. However, when the user clicks outside the circular region, you save the initial click position (shown in green). This defines a point which has a certain angle relative to the x-axis of your screen (you can find this easily with some trig), and it also defines the radius of the circle on which the user is working (in red). The release of the mouse adds a second point (blue). You then find the angle this point has relative to the center of the screen and the x-axis (just like before). You then project that angle onto your circle with the radius determined by the first click. The dark red arc defines the amount of rotation of the model.
This should be enough to get you started.
That will not be a good input method, I think. Because you will always need some travel distance to discriminate between a line and a curve, which means some input delay. Here is an alternative:
Only vertical mouse having their line crossing the center of the screen are considered vertical. Same for horizontal. In other cases it's considered a rotation, and to calculate its amplitude, calculate the angle between the last mouse location and the current location relatively to the center of the screen.
Alternatively you could use the center of the selected mesh if your application works like that.
You can't detect the "circular, along an arc" mouse movement with anywhere near the precision needed for 3d model viewing. What you want is something like this: http://thetechartist.com/?p=80
You nominate an axis (x, y, or z) using either keyboard shortcuts or on-screen axis indicators that you can grab with the mouse.
This will be much more precise than trying to detect an "arc" gesture. Any "arc" recognition would necessarily involve a delay while you accumulate enough mouse samples to decide whether an arc gesture has begun or not. Gesture recognition like this is non-trivial (I've done some gesture work with the Wii-mote). Similarly, even your simple "vertical" and "horizontal" mouse movement detection will require a delay for the same reason. Any "simple threshold to filter slight deviations" will make it feel dampened and weird.
For 3d viewing you want 1:1 mouse responsiveness, and that means just explicitly nominating an axis with a shortcut key or UI etc. For x-axis rotation, just restrict it to mouse x, y-axis to mouse y if you like. For z you could similarly restrict to x or y mouse input, or just take the total 2d mouse distance travelled. It depends what feels nicest to you.
As an alternative, you could try coding up support for a 3D mouse like the 3dConnexion SpaceExplorer.

WM_MOUSEMOVE not working with FPS camera implemetation in Direct3D

hey guys,
i am trying to implement an FPS=Style camera. The mouse movement is working but without even touching the mouse. The camera is going on all degrees without me even touching the mouse. Basically, the yaw and the pitch are getting wrong values from the mouse without the movement of the mouse itself.
here is the code for the win32 loop
case WM_MOUSEMOVE:
gCamera->Yaw() = (float)LOWORD(lparam);
gCamera->Pitch() = (float)HIWORD(lparam);
break;
the Yaw and Pitch methods basically return a reference to the data members mPitch and mYaw, and through them, i do the rotations for the basis vectors(right, up and look vectors)
Just to clarify, i WM_MOUSEMOVE is getting input(i checked through debugging), but it is getting very high and very wrong values because i am not even moving the mouse and because the camera is rotating in every direction like it just ate some rocket fuel.
P.S: i had to typecast the values because i am using the Yaw and the Pitch to create matrices, i have to use floats.
Appreciate the help, guys
Keep in mind your units. The WM_MOUSEMOVE lparam x & y values are in logical (screen pixel) coordinates, but most rotation values in games are expected in terms of degrees or radians. For instance, if the mouse is at say <400, 300> but your camera class expects radians, then you're multiplying a large number of rotations against some other (potentially varying) numbers in your transform math, potentially leading to crazy movement even though you're not moving the mouse. The solution in such a case is to convert your logical units into radians or degrees, using a scale factor of your choosing.
In response to further comments:
One way to think about it is to ask yourself the question: how many logical units of movement (by the mouse) do you want to correspond to 360 degrees of rotation?
For instance, if you decided you wanted mouse movement across the full width of the window to correspond to 360 degrees, then then mathematical relationship is
screenW * scaleFactor = 2 * PI
Solve for scaleFactor then apply it to future mouse values using:
mouseX * scaleFactor = orientationInRadians
Keep in mind, this approach would link an absolute mouse location to an absolute camera orientation (for at least one DOF), so you may instead want to track changes in mouse position, rather than absolute mouse position; and then calculate changes in orientation (radians) to apply to existing orientation. The same formula can be used to convert the delta (change amount) from logical coords to radians.