I'm working in GLSL, and need to calculate the angle between two 2D vectors fast and efficiently.
Given two vec2 vectors, for instance (30, 20) and (50, 50), I need to calculate the angle between them.
I'm currently using
acos(dot(vector1, vector2));
Although this doesn't seem to be giving me the angle correctly. Am I doing something wrong, or is this the right function to be using?
A vector dot product will compute the cosine of the angle between two vectors, scaled by the length of both vectors. If you want to get just the angle, you must normalize both vectors before doing the dot product.
The dot product alone will give you some very rough information about the angle between two vectors, even if they're not unit vectors:
If the dot product is 0, the vectors are 90 degrees apart (orthogonal or perpendicular).
If the dot product is less than 0, the vectors are more than 90 degrees apart.
If the dot product is greater than 0, the vectors are less than 90 degrees apart.
Related
i'm searching for an algoritm to find angle between camera and object in a picture, for example:
In the example picture we can see 30 degree between the camera point of view and the object (tv in our case).
is anyone knows any algoritm that solve this problem?
The Television makes up a plane with a normal. Now take the vector from a point on this plane, like the TV's center, and the camera: sin α equals to the dot-product of the two vectors divided by the product of both vectors' lengths. Use arcsin to obtain the angle (beware of radians vs. degrees). If neccessary, clamp the angle between 0° and 90°.
I am trying to attach 2d shape profiles to a spline curve. At certain points in the spline I get the weird twisting artifacts in my geometry as shown in the image. How can I avoid this using the Frenet-Frame equations?
My current calculations for the normal, binormal and tangent:
forward_tangent_vector = glm::normalize(pointforward - pointmid);
backward_tangent_vector = glm::normalize(pointmid - pointback);
second_order_tangent = glm::normalize(forward_tangent_vector - backward_tangent_vector);
binormal = glm::normalize(glm::cross(forward_tangent_vector,second_order_tangent));
normal = glm::normalize(glm::cross(binormal, forward_tangent_vector));
//translation matrix
T = glm::translate(T, pointmid);
normal_axis = glm::vec3(0, 1, 0);
rotationAxis = glm::cross(normal_axis, forward_tangent_vector);
rotationAngle = glm::acos(glm::dot(normal_axis, forward_tangent_vector));
//rotation matrix
R = glm::rotate(R, glm::degrees(rotationAngle), rotationAxis);
You fell victim to the hairy ball theorem:
A common problem in computer graphics is to generate a non-zero vector in R3 that is orthogonal to a given non-zero one. There is no single continuous function that can do this for all non-zero vector inputs. This is a corollary of the hairy ball theorem. To see this, consider the given vector as the radius of a sphere and note that finding a non-zero vector orthogonal to the given one is equivalent to finding a non-zero vector that is tangent to the surface of that sphere where it touches the radius. However, the hairy ball theorem says there exists no continuous function that can do this for every point on the sphere (i.e. every given vector).
Also see this: http://blog.sigfpe.com/2006/10/oriented-fish-and-hairy-balls.html
The problem lies in these two lines:
normal_axis = glm::vec3(0, 1, 0);
rotationAxis = glm::cross(normal_axis, forward_tangent_vector);
When forward_tangent_vector is colinear with (0,1,0), rotationAxis becomes (0,0,0). That's why you get a jolt in your pipe.
What you need to do instead of hardcoding (0,1,0), is to take the first derivative of the spline (velocity/tangent vector), take the second derivative of the spline (acceleration/normal vector), and take their cross products (binormal). Normalize these three vectors and you get the so-called Frenet-frame, a set of 3 mutually perpendicular vectors around the spline.
Note that your spline has to be C2-continuous, otherwise you would get similar "twists" caused by the discontinuities in the second derivative (aka. acceleration/normal vector).
Once you have the Frenet-frame, it's a matter of a simple change of basis to work in that coordinate system. Don't mess around with glm::rotate, just put the x,y,z unit vectors into a matrix as rows (or columns? I'm not sure what convention GLM uses...) and that'll be your transformation matrix.
I would like to stick a moving car to a curvy terrarian. I can calculate the y coordinate (which is height in my case) for each wheel. These 4 points forms a plane. I don't know how to calculate the rotation matrix from these 4 pints so I can apply it to the car. So this is what I would like to achieve:
calculateRotationMatrix(p1,p2,p3,p4);
BTW I am using c++ and openGL.
Could anybody help me out here?
If you guarantee that all 4 points lie on one plane, then the problem is not that hard to solve: Let's call the points (A,B,C,D) and we define a up vector (UP = [0,1,0])
1) Calculate the plane normal (N)
N = normalize(cross(B-A, C-A));
2) Calculate the rotation axis (R)
R = normalize(cross(N,UP))
3) Calculate rotation angle (alpha)
alpha = dot(N, UP)
The resulting matrix is then the one that rotates around R by an angle of alpha. If your matrix library does not support creating rotation axis around arbitrary axis, you can find the form here.
Note, that there is a singularity when alpha is very small (N will then vanish), so you should only calculate the matrix if alpha is sufficiently large. It might also be that case that some of the vectors point to the opposite direction depending on the winding order in which the points are defined. In this case just switch the two parameters of the cross function.
I have a simple 3D LookAt vector, and I wish to rotate the player model (a simple cube) to show where the player/cube is looking at.
For sideways camera movement I've managed to figure it out and do the following:
glTranslatef(position.x, position.y, position.z);
glRotatef(atan2(lookAt.z, lookAt.x) * 180 / PI, 0, 1, 0);
Now I know that to get up-down camera movement to map to the rendered cube model, I need to rotate the cube around it's x and z axes as well, but I can't seem to figure out what formula to use for those two.
OpenGL will rotate the whole coordinate system (whole space, not only a cube) so after first rotation you just need to rotate only around z axis.
// first rotation
glRotatef(-atan2(lookAt.z, lookAt.x) * 180 / PI, 0, 1, 0);
// second rotation
float d = sqrt(pow(lookAt.x,2) + pow(lookAt.z,2));
float pitch = atan2(lookAt.y, d);
glRotatef(pitch * 180 / PI, 0, 0, 1);
First and second rotation:
I assume your model is looking along x axis (red arrow). I also assume lookAt is given relative to the position of the model.
If you're familiar with matrix math, matrices are an easier way to think about it. If you're not familiar with matrices, this series explains how to use them to solve common game development problems: https://www.youtube.com/playlist?list=PLW3Zl3wyJwWNQjMz941uyOIq3Nw6bcDYC Getting good with matrices is a good idea if you want to be a 3D game programmer.
For your problem, you want to make a translation/rotation matrix which will transform the box to the proper place for you. You can make a translation matrix and a rotation matrix individually, and then at the end take the product of the two. I'll try to break that down.
The translation matrix is simple, if your position is then your matrix will be
To construct a rotation matrix, you need to rotate the standard basis vectors the way you want. Then when you create a matrix from those rotated basis vectors, the matrix will rotate other vectors in the same way. As an example of that, take the standard basis vectors:
Now I'm going to rotate and around by 90 degrees clockwise:
Now put them into a matrix:
and you have R is a matrix that rotates things around by 90 degrees.
In your case you want to rotate stuff such that it faces a vector that you provide. That makes things easy, we can calculate our basis vectors from that vector. If your vector is then and we can solve for the other two basis vectors using cross products. You know that the character won't ever roll their view (right?) so we can use the global up vector as well. I'll call the global up vector . In your case you're using y as the "up" dimension so the global up vector will be
Then:
In the first line you do a cross product between the view vector and the up vector to get a vector orthogonal to both - this will serve as the third basis vector after it is normalized, which is the second line. In the third line another cross product generates the second basis vector. These three vectors represent what happens when the standard basis vectors are rotated the way you want them to be. Use them as the columns in a matrix like so:
Now the last step in the math is to make a final matrix that will do both translation and rotation, and this step is easy:
Then load that matrix into OpenGL with glLoadMatrix:
glLoadMatrixf(&M);
All of this gets explained in the video series I linked as well :)
I have many 3D planes. The thing that I need to know is the way of computing aspect angle.
I hope, I can compute the aspect angle by using the projected normal vector of each plane (my plane equation is ax+by-z+c=0; so normal vector of this plane is a,b,-1) to the XY plane. Then, from the Y axis I can compute the aspect angle. But, I don’t know how to get the projected Normal vector after I projected to XY plane. Then, can I apply the equation which gives angle between two vectors to compute angle of my desired vector from the y axis.
On the other hand, I found, aspect angle is defined as the angle between any line which passes along the steepest slope of the plane and north direction (here, Y axis). Does this definition will follow, with my proposed way that is taking normal vectors? I mean, does the projected normal vector always given along the steepest slope of the plane? Also, some one told me, that this problem should consider as a 2D problem.
Please comment me and send me the relevant formulae in order to compute aspect angle. Thank you.
Some quick googling reveals the definition of the aspect angle.
http://www.answers.com/topic/aspect-angle
It's the angle between the geographic north on the northern hemisphere and the geographic south on the southern hemisphere. So basically it's a measure how much a slope faces the closest pole.
If your world is planar as opposed to spherical it will simplify things, so yes - A 2D problem. I'll make this assumption having the following implications:
In a spherical world the north pole is a point on the sphere. In a planar world the "pole" is a plane at infinity. Think about a plane somewhere far away in your world denoting "north". Only the normal of this plane is important in this task. The unit normal of this plane is N(nz,ny,nz).
Up is a vector pointing up U(ux,uy,yz). This is the unit normal vector of the ground plane.
The unit normal vector of the plane V(a,b,c) can now be projected onto a vector P on the ground plane as usual: P = V - (V dot U) U
Now it's easy to measure the aspect angle of the plane - It's the angle between the "pole"-plane N and the projected plane normal P given by acos(P dot N).
Since north is positive Y-axis for you we have N = (0, 1, 0). And then I guess you have up is U = (0, 0, 1), positive Z. This will simplify things even more - To project on the ground plane we just strip the Z-part. The aspect angle is then the angle between (a,b) and (0,1).
aspectAngle = acos(b / sqrt(a*a + b*b))
Note that planes parallell with the ground plane does not have a well-defined aspect angle since there is no slope to measure the aspect angle from.
What kind of surfaces are you working with? TINS (Triangular Irregular Networks) or DEMs (Digital Elevation Models)?
If you are using raster imagery to create your surfaces, the algorithm for calculating aspect is basically a moving window, which checks a central pixel plus the 8 neighbors.
Compare the central one with each neighbor and check for difference in elevation over distance (rise over run). You can parametrize the distance checks (north, south, east and west neighbors are at distance = 1 and northwest, southwest, southeast and northeast are at distance = sqrt(2)) to make it faster.
You can ask this question on gis.stackexchange also. Many people will be able to help you there.
Edit:
http://blog.geoprocessamento.net/2010/03/modelos-digitais-de-elevacao-e-hidrologia/
this website, altought in portuguese, will help you visualize the algorithm. After calculating the highest slope between a central cell and it's eight neighbors, you assign 0, 2, 4, 8, 16, 32, 64 or 128, depending on the location of the cell that presented highest slope between center and neighboors.