I have been following this article on Frustum culling, and I need some help understanding the vector math behind it. More specifically, what are the vectors of 'up' and 'right' he talks about? What values do they hold? Sorry for the brief and unexciting question, but I am really stuck on this. Any help is appreciated! Thanks
From the article:
A couple more unit vectors are required, namely the up vector and the right vector. The former is obtained by normalizing the vector (ux,uy,uz) (the components of this vector are the last parameters of the gluLookAt function); the latter is obtained with the cross product between the up vector and the d vector.
up is equal to (ux, uy, uz) / ||(ux, uy, uz)||, which is just a unit vector pointing the same direction as (ux, uy, uz).
It's equal to (ux / sqrt(ux^2 + uy^2 + uz^2), uy / sqrt(ux^2 + uy^2 + uz^2), uz / sqrt(ux^2 + uy^2 + uz^2))
right is equal to up x d. I don't really want to expand that out.
Related
Is it possible, To get a Forward, Right and Up Directional Vectors just from Euler Angles, no quaternions or Matrices. I don't mind if it is slower, how fast the code is isn't my main goal. I've been wrapping my head about quaternions and Matrices for 2 weeks, and it didn't work, when I came here I got a response that didn't event work or gave any useful information. I know there is a huge ton of questions like this But I searched over all possible sites and the answer was always to use Quaternions or Matrices, so is it even possible ?
In 3D To transform vector without matrices You just rewrite the matrix*vector operation
(x',y',z') = M*(x,y,z)
into:
x' = m[0][0]*x + m[0][1]*y + m[0][2]*z;
y' = m[1][0]*x + m[1][1]*y + m[1][2]*z;
z' = m[2][0]*x + m[2][1]*y + m[2][2]*z;
where the matrix m[row][col] is (just 3x3 rotational part) result of 3 axis aligned rotation matrices:
multiplied together in order you use (algebraicaly as equations you can do this in any math SW like Derive for Windows if you too lazy like me) for example:
Both images where taken from wiki so for example
m[0][0]=(cos(a)*cos(b))
m[0][1]=((cos(a)*sin(b)*sin(c))-(sin(a)*cos(c)))
m[0][2]=((cos(a)*sin(b)*cos(c))-(sin(a)*sin(c)))
x' = m[0][0]*x + m[0][1]*y + m[0][2]*z;
-----------------------------------------------------
x' = (cos(a)*cos(b))*x + ((cos(a)*sin(b)*sin(c))-(sin(a)*cos(c)))*y + ((cos(a)*sin(b)*cos(c))-(sin(a)*sin(c)))*z
I am too lazy to write the rest (that is one of the reason why matrices are used its more convenient). Also for the sake of speed precompute the sin and cos values of a,b,c angles into variables like cosa,cosb,cosc,sina,sinb,sinc and use that instead of calling the same slow goniometric functions again and again so...
x' = (cosa*cosb)*x + ((cosa*sinb*sinc)-(sina*cosc))*y + ((cosa*sinb*cosc)-(sina*sinc))*z
Now you just use this to transform 3 unit directions (1,0,0),(0,1,0),(0,0,1) and the result will be your vectors.
for more info about the topic see:
Is there a way to calculate 3D rotation on X and Y axis from a 4x4 matrix ...
How can we use vector and scalar in games? What benefit from that.
Could someone please indicate precisely the difference between a scalar and a vector in games field ? I find no matter how many times I try to understand but I maybe need examples for that.
A scalar is just another word for a number. The distinction is that a scalar is a number that is part of a vector. There is nothing special about a scalar.
A vector is a set of numbers (one or more) that define something, in the most common case you have 2 numbers representing a 2D vector or 3 numbers representing a 3D vector. The abstract notion for a vector is simply an arrow.
Take a piece of graph paper. Select any point on that paper and call it the origin. Its coordinate will be x = 0, y = 0. Now draw a straight line from that point in any direction and any length. To describe that arrow you need to define the vector. Count how far across the page the end of the arrow is from the start (origin) and that is the x component. Then how far up the page and that is the y component.
You have just created a vector that has two numbers (x,y) that completely describe the arrow on the paper. This type of vector always starts at zero. You can also describe the vector by its direction (ie north, east, south...) and length.
In 3D you need 3 numbers to describe any arrow. (x,y,z)
Vectors are very handy. You can use a vector to describe how fast something is moving and in what direction. The vector represents a little arrow that starts where the object is now and ends where the object will be in the next time unit.
Thus an object at coordinate x,y has a vector velocity(0.2,0.3). To calculate the position of the object in the next time unit just add the vector to the coordinate
newXPos = currentXPos + velocityVectorX
newYPos = currentYPos + velocityVectorY
If you want to slow the speed by half you can multiply the vector by 0.5
velocityVectorX = velocityVectorX * 0.5
velocityVectorY = velocityVectorY * 0.5
You do the same to increase the speed.
velocityVectorX = velocityVectorX * 2
velocityVectorY = velocityVectorY * 2
You may have an object in 3D space that has many forces acting on it. There is gravity a vector (arrow) pointing down (G). The force of the air resistance pointing up (R). The current velocity another arrow pointing in the direction it is traveling (V). You can have as many as you like (need) to describe all the forces that push and pull at the object. When you need to calculate the position of the object for the next instance in time (say one second) you just add all the force vectors together to get the total force as a vector and add that to the objects position
Object.x = Object.x + G.x + R.x + V.x;
Object.y = Object.y + G.y + R.y + V.y;
Object.z = Object.z + G.y + R.z + V.z;
If you just want the velocity
V.x = V.x + G.x + R.x;
V.y = V.y + G.y + R.y;
V.z = V.z + G.y + R.z;
That is the new velocity in one second.
There are many things that can be done with a vector. A vector can be used to point away from a surface in 3D, this vector is called a surface normal. The you create a vector from a point on that surface pointing to a light. The cosine of the angle between the two vectors is how much light the surface will reflect.
You can use a vector to represent the three direction in space an object has. Say a box, there is a 3D vector pointing along the width, another along the height and the last along the depth. The length of each vector represents the length of each side. You can make another vector to represent how far the corner of the box is from the origin (any known point) In 3D these 4 vectors are used to represent the object and is called a transformation matrix (just another type of vector made up of vectors)
The list of things vectors can do is endless.
The basics is just like number, you can add, subtract, multiply and divide and vector.
Then there are a host of special functions for vectors, normalize, transform, dot product and cross product to name but a few. For these things people normally use a library that does all this for you. My view is that if you really want to learn about vectors and how they are used write your own vector library at some point until then use a library.
Hope that cleared the mud a little bit for you, it is always difficult to describe something you have used for a long time to someone that is new to it so feel free to ask questions in the comments if you need.
(In three dimensions) I'm looking for a way to compute the signed angle between two vectors, given no information other than those vectors. As answered in this question, it is simple enough to compute the signed angle given the normal of a plane to which the vectors are perpendicular. But I can find no way to do this without that value. It's obvious that the cross product of two vectors produces such a normal, but I've run into the following contradiction using the answer above:
signed_angle(x_dir, y_dir) == 90
signed_angle(y_dir, x_dir) == 90
where I would expect the second result to be negative. This is due to the fact that the cross product cross(x_dir, y_dir) is in the opposite direction of cross(y_dir, x_dir), given the following psuedocode with normalized input:
signed_angle(Va, Vb)
magnitude = acos(dot(Va, Vb))
axis = cross(Va, Vb)
dir = dot(Vb, cross(axis, Va))
if dir < 0 then
magnitude = -magnitude
endif
return magnitude
I don't believe dir will ever be negative above.
I've seen the same problem with the suggested atan2 solution.
I'm looking for a way to make:
signed_angle(a, b) == -signed_angle(b, a)
The relevant mathematical formulas:
dot_product(a,b) == length(a) * length(b) * cos(angle)
length(cross_product(a,b)) == length(a) * length(b) * sin(angle)
For a robust angle between 3-D vectors, your actual computation should be:
s = length(cross_product(a,b))
c = dot_product(a,b)
angle = atan2(s, c)
If you use acos(c) alone, you will get severe precision problems for cases when the angle is small. Computing s and using atan2() gives you a robust result for all possible cases.
Since s is always nonnegative, the resulting angle will range from 0 to pi. There will always be an equivalent negative angle (angle - 2*pi), but there is no geometric reason to prefer it.
Signed angle between two vectors without a reference plane
angle = acos(dotproduct(normalized(a), normalized(b)));
signed_angle(a, b) == -signed_angle(b, a)
I think that's impossible without some kind of reference vector.
Thanks all. After reviewing the comments here and looking back at what I was trying to do, I realized that I can accomplish what I need to do with the given, standard formula for a signed angle. I just got hung up in the unit test for my signed angle function.
For reference, I'm feeding the resulting angle back into a rotate function. I had failed to account for the fact that this will naturally use the same axis as in signed_angle (the cross product of input vectors), and the correct direction of rotation will follow from which ever direction that axis is facing.
More simply put, both of these should just "do the right thing" and rotate in different directions:
rotate(cross(Va, Vb), signed_angle(Va, Vb), point)
rotate(cross(Vb, Va), signed_angle(Vb, Va), point)
Where the first argument is the axis of rotation and second is the amount to rotate.
If all you want is a consistent result, then any arbitrary way of choosing between a × b and b × a for your normal will do. Perhaps pick the one that's lexicographically smaller?
(But you might want to explain what problem you are actually trying to solve: maybe there's a solution that doesn't involve computing a consistent signed angle between arbitrary 3-vectors.)
sorry - I should know this but I don't.
I have computed the position of a reference frame (S1) with respect to a base reference frame (S0) through two different processes that give me two different 4x4 affine transformation matrices. I'd like to compute an error between the two but am not sure how to deal with the rotational component. Would love any advice.
thank you!
If R0 and R1 are the two rotation matrices which are supposed to be the same, then R0*R1' should be identity. The magnitude of the rotation vector corresponding to R0*R1' is the rotation (in radians, typically) from identity. Converting rotation matrices to rotation vectors is efficiently done via Rodrigues' formula.
To answer your question with a common use case, Python and OpenCV, the error is
r, _ = cv2.Rodrigues(R0.dot(R1.T))
rotation_error_from_identity = np.linalg.norm(r)
You are looking for the single axis rotation from frame S1 to frame S0 (or vice versa). The axis of the rotation isn't all that important here. You want the rotation angle.
Let R0 and R1 be the upper left 3x3 rotation matrices from your 4x4 matrices S0 and S1. Now compute E=R0*transpose(R1) (or transpose(R0)*R1; it doesn't really matter which.)
Now calculate
d(0) = E(1,2) - E(2,1)
d(1) = E(2,0) - E(0,2)
d(2) = E(0,1) - E(1,0)
dmag = sqrt(d(0)*d(0) + d(1)*d(1) + d(2)*d(2))
phi = asin (dmag/2)
I've left out some hairy details (and these details can bite you). In particular, the above is invalid for very large error angles (error > 90 degrees) and is imprecise for large error angles (angle > 45 degrees).
If you have a general-purpose function that extracts the single axis rotation from a matrix, use it. Or if you have a general-purpose function that extracts a quaternion from a matrix, use that. (Single axis rotation and quaternions are very closely related to one another).
I'm playing with per pixel lighting shaders and i don't know one thing: What is half vector of light source ?
vec3 halfVector = normalize(gl_LightSource[1].halfVector.xyz);
I would like i you can explain it in math rows, i understand math better than words :)
From this post:
A "halfway vector" (if you mean that by "half vector") is the unit vector at the half angle between two other vectors. Normally the halfway vector [...] is computed between the vector to the viewer v and the light source l:
h := ( v + l ) / || v + l ||
The half vector therefore is the unit angle bisector of view- and light vector.
Edit: For a complete explanation of the lighting model including the half vector, just see the Blinn-Phong wikipedia article
The the answer by Dario is correct, but since the question was for GLSL, here is the appropriate code:
vec3 hf = normalize(v + l);
Generally the "THE" half vector is the vector between the light and the view vector. It is generally used as input to the specular bit of the Blinn-Phong equations.
this was my solution:
vec3 halfVector = normalize(lightDirection + viewDirection);
EDIT: it is not 100% correct but working when you want to do it more simple.