I'm writing a screensaver with a bouncing ball (x and y, does not bounce in Z) in C++ using OpenGL. When this ball touches the edges of the screen, a small patch of damage will appear on the ball. (When the ball is damaged enough, it will explode.) Finding the part of the ball to damage is the easy part when the ball isn't rotating.
The algorithm I decided for this is that I'm keeping the position left most, right most, top most and bottom most vertex. For every collision, I obviously need to know which screen edge it hit. Before the ball could roll, when it touches a screen edge, if it hit the left screen edge, I know the left-most vertex is the point on the ball that took a hit. From there, I get all vertices that are within d distance from that point. I don't need the actual vertex that was hit, just the point on the ball's surface.
Doing this, I don't need to read all vertices, translate them by the x,y position of the ball and see which are off-screen. Doing this would solve all my problems but would be slow as hell.
Currently, the ball's rotation is controlled by pitch, yaw and roll. The problem is, what point on the ball's outer surface has touched the edge of the screen given my yaw, pitch and roll angles? I've looked into keeping an up, right and direction vector but I'm totally new to this and as someone might notice, totally lost. I've read the rotation matrix article on Wikipedia several times and still drawing a blank. If I got rid of one rotation angle it would be much simpler but I would prefer not to.
If you have your rotation angles then you can recreate the model view matrix in your code. With that matrix you can apply the rotation to the vertices of the mesh (simply by multiplication) and then find the left most (or whatever) vertex as you did before.
This article explains how to construct the rotation matrix with the angles you have.
Related
I'm working on a physics simulation of projectiles, and I'm stuck on the ground collision. I have a ground made of quads,
I have the points stored in an array, so I thought that if I take the quad where the collision happen and calculate the angles of the quad (in x and z directions) I can then use that to change the velocity of the projectile.
This is where I'm stuck. I thought I should find the lowest and the highest point, then find the vector between them, but this will not give the angles in all directions, which is what I want. I know there must be a way of doing this, but how?
What you want is a normal of a quad.
Here's an answer that shows you how to get a quad's normal
After you got the normal, you need to calculate the force of the collision's response. Its direction is the normal of the quad and the strength is the strength the projectile exerts in the direction of the quad. Exerted force is calculated by using dot product of the projectile's velocity and reversed quad's normal (Here's a wiki link for the dot product)
The response vector should be this:
Vector3 responseForce = dot(projectile.vel, -1 * quad.normal) * quad.normal;
projectile.vel += responseForce;
I've got a 3D scene and want to offer an API to control the camera. The camera is currently described by its own position, a look-at point in the scene somewhere along the z axis of the camera frame of reference, an “up” vector describing the y axis of the camera frame of reference, and a field-of-view angle. I'd like to provide at least the following operations:
Two-dimensional operations (mouse drag or arrow keys)
Keep look-at point and rotate camera around that. This can also feel like rotating the object, with the look-at point describing its centre. I think that at some point I've heard this described as the camera “orbiting” around the centre of the scene.
Keep camera position, and rotate camera around that point. Colloquially I'd call this “looking around”. With a cinema camera this might perhaps be called pan and tilt, but in 3d modelling “panning” is usually something else, see below. Using aircraft principal directions, this would be a pitch-and-yaw movement of the camera.
Move camera position and look-at point in parallel. This can also feel like translating the object parallel to the view plane. As far as I know this is usually called “panning” in 3d modelling contexts.
One-dimensional operations (e.g. mouse wheel)
Keep look-at point and move camera closer to that, by a given factor. This is perhaps what most people would consider a “zoom” except for those who know about real cameras, see below.
Keep all positions, but change field-of-view angle. This is what a “real” zoom would be: changing the focal length of the lens but nothing else.
Move both look-at point and camera along the line connecting them, by a given distance. At first this feels very much like the first item above, but since it changes the look-at point, subsequent rotations will behave differently. I see this as complementing the last point of the 2d operations above, since together they allow me to move camera and look-at point together in all three directions. The cinema camera man might call this a “dolly” shot, but I guess a dolly might also be associated with the other translation moves parallel to the viewing plane.
Keep look-at point, but change camera distance from it and field-of-view angle in such a way that projected sizes in the plane of the look-at point remain unchanged. This would be a dolly zoom in cinematic contexts, but might also be used to adjust for the viewer's screen size and distance from screen, to make the field-of-view match the user's environment.
Rotate around z axis in camera frame of reference. Using aircraft principal directions, this would be a roll motion of the camera. But it could also feel like a rotation of the object within the image plane.
What would be a consistent, unambiguous, concise set of function names to describe all of the above operations? Perhaps something already established by some existing API?
I'm making a skybox in my game. The game has a solar system with some things in it (to start, the sun and the earth, with stars in the background). The player is on one planet in this solar system. The solar system is represented to the player using a skybox, with 2D sprites projected onto the skybox in the corresponding positions. The Skybox is rendered with OpenGL (actually, Java's LWJGL) [1]
First things first, all of the bodies are being tracked in 3D space. I can obtain their coordinates, relative directions, etc. All orbits are defined independently (aka, occur on arbitrary planes). In addition, planets have Quaternion rotations. Rendering the system in full 3D, there are no problems.
Projecting the system to the skybox is another matter entirely. In theory, I figure that I should be able to do it like this;
1. Calculate direction vector of where the player is looking (full rotations are not relevant - the vector just has to point in the right direction).
2. Multiply this direction vector with their planet's orientation (Quaternion) to calculate the "view direction"
3. Calculate direction vector from the planet to the object being viewed
4. Find the rotation between the vectors, and rotate the skybox accordingly.
However, when I feed OpenGL my angles, Gimbal Locking occurs and orbits that should be straight: go all bendy (although rotations around one single axis work fine). In what ways can I attempt to prevent this from happening? I'm at a loss.
[1]: My terrain is actually a flat square voxel grid, and I scale the player's coordinates onto it, then pretend that it is a 3D planet.
I am building a number of rooms with different shapes: Parallelogram, Rectangle, Rhombus, Square and etc. The viewer is supposed to look at the rooms from different corners, turn his head to right and left, and guess the shape of the room. So here “the perception of the angles between walls” is very important. My problems are these:
1) most of the acute angles seem to be 90 degrees from the distance,
2) the angles between walls as well as the length of the walls seem to change when the viewer turns his head left or right.
As I have read until now, it is the consequence of using Perspective projection; however, with Orthogonal projection I would have no depth (no perception of depth) in the screen and since I am inside of the room, the size of the room should be bigger than clipped area which produces a quite rubbish image.
I just want to know that is there any way to avoid or at least minimize this deformation effect? Should I build my own projection (something between glortho and glprospective)?
It is also worth mentioning that I use "glutlookatfunction" for positioning the camera and lookat points . The eye position is always one of the room corners and the initial lookat point is the opposite corner of the viewer.By pressing right and left arrow keys , the lookat point moves on the imaginary circle serrounding the room , just like the most of the OpenGL programs I have seen until now .Do you think it would be better if I move the lookat point on the walls ? Or rotate the room instead of changing the look at point ?
I added some pictures for better illustration of my problem :
This is my parallelogram room :
parallelogram.png
As you can see here , the acute angle ,which is supposed to be 60 degrees ,seems to be at least 90 degrees . And this is my rectangle room, which doesn't give you the sense of being in a rectangle room at all :
Rectangle.png
I'd say, without seeing the problem in action, that your camera FOV is too large.
From your comment, your camera has a 112.5° horizontal FOV, which I believe introduces 'unnatural distortions' on the edges of the screen : simple OpenGL perspective projection is linear and suffers from too wide FOVs.
You may want to take a look at this article comparing cameras to human eyes, as you want to jauge the perception of your users.
You should try to reduce the horizontal FOV of your camera, perhaps in the 80-90° range to see if it helps.
As a last resort, you could switch to non-linear projections, but you should make an educated choice before switching to this, there should be psychophysics research available (such as this) that may help you.
I was trying to understand lesson 9 from NEHEs tutorial, which is about bitmaps being moved in 3d space.
the most interesting thing here is to move 2d bitmap texture on a simple quad through 3d space and keep it facing the screen (viewer) all the time. So the bitmap looks 3d but is 2d facing the viewer all the time no matter where it is in the 3d space.
In lesson 9 a list of stars is generated moving in a circle, which looks really nice. To avoid seeing the star from its side the coder is doing some tricky coding to keep the star facing the viewer all the time.
the code for this is as follows: ( the following code is called for each star in a loop)
glLoadIdentity();
glTranslatef(0.0f,0.0f,zoom);
glRotatef(tilt,1.0f,0.0f,0.0f);
glRotatef(star[loop].angle,0.0f,1.0f,0.0f);
glTranslatef(star[loop].dist,0.0f,0.0f);
glRotatef(-star[loop].angle,0.0f,1.0f,0.0f);
glRotatef(-tilt,1.0f,0.0f,0.0f);
After the lines above, the drawing of the star begins. If you check the last two lines, you see that the transformations from line 3 and 4 are just cancelled (like undo). These two lines at the end give us the possibility to get the star facing the viewer all the time. But i dont know why this is working.
And i think this comes from my misunderstanding of how OpenGL really does the transformations.
For me the last two lines are just like undoing what is done before, which for me, doesnt make sense. But its working.
So when i call glTranslatef, i know that the current matrix of the view gets multiplied with the translation values provided with glTranslatef.
In other words "glTranslatef(0.0f,0.0f,zoom);" would move the place where im going to draw my stars into the scene if zoom is negative. OK.
but WHAT exactly is moved here? Is the viewer moved "away" or is there some sort of object coordinate system which gets moved into scene with glTranslatef? Whats happening here?
Then glRotatef, what is rotated here? Again a coordinate system, the viewer itself?
In a real world. I would place the star somewhere in the 3d space, then rotate it in the world space around my worlds origin, then do the moving as the star is moving to the origin and starts at the edge again, then i would do a rotate for the star itself so its facing to the viewer. And i guess this is done here. But how do i rotate first around the worlds origin, then around the star itself? for me it looks like opengl is switching between a world coord system and a object coord system which doesnt really happen as you see.
I dont need to add the rest of the code, because its pretty standard. Simple GL initializing for 3d drawings, the rotating stuff, and then the simple drawing of QUADS with the star texture using blending. Thats it.
Could somebody explain what im misunderstanding here?
Another way of thinking about the gl matrix stack is to walk up it, backwards, from your draw call. In your case, since your draw is the last line, let's step up the code:
1) First, the star is rotated by -tilt around the X axis, with respect to the origin.
2) The star is rotated by -star[loop].angle around the Y axis, with respect to the origin.
3) The star is moved by star[loop].dist down the X axis.
4) The star is rotated by star[loop].angle around the Y axis, with respect to the origin. Since the star is not at the origin any more due to step 3, this rotation both moves the center of the star, AND rotates it locally.
5) The star is rotated by tilt around the X axis, with respect to the origin. (Same note as 4)
6) The star is moved down the Z axis by zoom units.
The trick here is difficult to type in text, but try and picture the sequence of moves. While steps 2 and 4 may seem like they invert each other, the move in between them changes the nature of the rotation. The key phrase is that the rotations are defined around the Origin. Moving the star changes the effect of the rotation.
This leads to a typical use of stacking matrices when you want to rotate something in-place. First you move it to the origin, then you rotate it, then you move it back. What you have here is pretty much the same concept.
I find that using two hands to visualize matrices is useful. Keep one hand to represent the origin, and the second (usually the right, if you're in a right-handed coordinate system like OpenGL), represents the object. I splay my fingers like the XYZ axes to I can visualize the rotation locally as well as around the origin. Starting like this, the sequence of rotations around the origin, and linear moves, should be easier to picture.
The second question you asked pertains to how the camera matrix behaves in a typical OpenGL setup. First, understand the concept of screen-space coordinates (similarly, device-coordinates). This is the space that is actually displayed. X and Y are the vectors of your screen, and Z is depth. The space is usually in the range -1 to 1. Moving an object down Z effectively moves the object away.
The Camera (or Perspective Matrix) is typically responsible for converting 'World' space into this screen space. This matrix defines the 'viewer', but in the end it is just another matrix. The matrix is always applied 'last', so if you are reading the transforms upward as I described before, the camera is usually at the very top, just as you are seeing. In this case you could think of that last transform (translate by zoom) as a very simple camera matrix, that moves the camera back by zoom units.
Good luck. :)
The glTranslatef in the middle is affected by the rotation : it moves the star along axis x' to distance dist, and axis x' is at that time rotated by ( tilt + angle ) compared to the original x axis.
In opengl you have object coordinates which are multiplied by a (a stack of) projection matrix. So you are moving the objects. If you want to "move a camera" you have to mutiply by the inverse matrix of the camera position and axis :
ProjectedCoords = CameraMatrix^-1 . ObjectMatrix . ObjectCoord
I also found this very confusing but I just played around with some of the NeHe code to get a better understanding of glTranslatef() and glRotatef().
My current understanding is that glRotatef() actually rotates the coordinate system, such that glRotatef(90.0f, 0.0f, 0.0f, 1.0f) will cause the x-axis to be where the y-axis was previously. After this rotation, glTranslatef(1.0f, 0.0f, 0.0f) will move an object upwards on the screen.
Thus, glTranslatef() moves objects in accordance with the current rotation of the coordinate system. Therefore, the order of glTranslatef and glRotatef are important in tutorial 9.
In technical terms my description might not be perfect, but it works for me.