I know a rotation matrix (or quaternion) of a body in starting position and in end position. The body was tilted in between around three vectors which are known. Is there a way to estimate the angles the body was tilted around these vectors just by knowing the end orientation of the body?
If body rotation is limited in given time period (for example, it does not accomplish two turnovers etc) and direction changes smoothly, then you can consider using of SLERP - spherical linear interpolation.
If you have initial tilt vector p0 (consisting of direction cosines) and ending p1, you can use geometric SLERP to get direction cosines as components of interpolated direction vector
Related
I have a 2D shape (a circle) that I want to extrude along a 3D curve to create a 3D tube mesh.
Currently the way I generate cross-sections along the curve (which form the basis of the resulting mesh) is to take every control point along the curve, create a 3D transform matrix for it, then multiply the 2D points of my circle by those curve-point matrices to determine their location in 3D space along the curve.
To create the matrix (from 3 vectors), I use the tangent on the curve as the up vector, world-up ([0,1,0]) as the forward vector, and the cross product of the up/forward vectors as the right vector. All three vectors are also orthogonalized during the process to create the final matrix.
The problem comes when my curve tangent is identical to the world-up axis. Ie, my tangent vector is [0,1,0] and the world-up is [0,1,0]....since the cross product of two parallel vectors is not explicit....the resulting extruded mesh has artifacts along those areas of the curve (pinching, twisting, etc).
I thought a potential solution would be to use the dot product of the curve tangent and the world-up as an interpolation value to shift my forward vector from world-up to world-right...in other words, as a curve tangent approaches [0,1,0], my forward vector approaches [1,0,0]...but that results in unwanted twisting along the final mesh as well.
How can I extrude my shape along a curve in a consistent manner that has no flipping/artifacts/twisting? I know it's possible since various off-the-shelf 3D applications can do it...I'm just not sure how.
One way I would approach this is to consider my tangent vector to the 3D curve as actually being a normal vector of the plane I am interested into.
Let's say, the tangent vector is
All you need now is two other vectors that are othoghonal to it, so let's.
Let's construct v like so:
(rotating the coordinates). Because v is the result of the cross product of u and something else, you know that v is orthogonal to u.
(This method will not work if u have equal x,y,z coordinates, in that case, construct the other vector by adding random numbers to at least two variables, rince&repeat).
Then you can simply construct w like before:
normalize and go.
I have a spherical heightfield, defined by a function f(x, y, z) which returns the distance from the origin of the surface of the heightfield of a line which passes from the origin through (x,y,z).
(In other words, the isosurface for my heightfield is |x,y,z| = f(x,y,z).)
(Also, for the sake of discussion below, I'm going to assume that surface(x,y,z) is the location of the point on the surface directly below (x,y,z).)
When rendering this, I need to calculate the normal for any point on the heightfield. What's the cheapest way of doing this?
To calculate the normal of a point on a rectangular heightfield, the usual trick is to offset (x,y,z) slightly in two directions parallel to the nominal surface, calculate three points on the heightfield to form a triangle, and then use the cross product to calculate the triangle's normal. This is easy as the three points can simply be surface(x,y,z), surface(x+1,y,z) and surface(x,y+1,z) (or similar). But for a spherical heightfield it's a little trickier because the normal can point in any direction. Simply displacing by x and y won't do because if two of my points fall on a radius, then surface() of them will return the same location and I won't get a triangle.
In the past what I've done is to use the vector <x,y,z> as a radius from the sphere's origin; then calculate a vector perpendicular to it; then rotate this vector around <x,y,z> to give me my three points. But this is fiddly and expensive and shouldn't be necessary. There must be a cheaper way. What is it?
Calculate the surface() points and, if they are close enough to cause problems, carry out the more expensive (but accurate) calculation; otherwise, use the cheap/easy calculation.
I want to use the minkowski sum to predict the exact point of collision between two convex shapes. By my understanding the point where the velocity vector intersects with the minkowski sum is the amount I have to move my object along the vector so they just touch (I already know they will collide). Here's an example of what I mean (for simplicity reasons I just used rectangles):
I mean I could just calculate the intersection with every line of the convex hull and just use the closest but that seems horribly inefficient. My idea was to calculate the simplex closest to the vector but I have no idea how best to do it. I found a algorithm which calculates the smallest distance between to objects or to be more precise the smallest distance from the minkowski sum to the origin (http://www.codezealot.org/archives/153). One part of the algorithm tries to find the simplex closest to origin which is kinda what I want to do. I tried to change it to my needs but I wasn't successful. To me it sounds like there should be a very simple solution but I am not that good with vector math.
I hope I could make my problem clear since my english is not so good :D
You can transform the problem as follows:
1) rotate the plane so that the velocity vector becomes horizontal
2) consider the portions of the polygon outlines facing each other (these are two convex polylines); now you have to find the shortest horizontal distance between these two polylines
3) through every vertex of one of the polylines, draw an horizontal line; this will parition the plane into a set of horizontal slices
4) transform every slice using a shear transformation that brings the two vertices defining it onto the Y axis by horizontal moves; this transform preserves horizontal distances
5) while the first polyline is transformed into a straight line (the Y axis), the other polyline is transformed into another polyline; find the vertex(es) closest to the Y axis. This gives you the length of the collision vector.
As a by-product, step 2) will tell you if the polygons do collide, if the ranges of Y values overlap.
I have a 3d object which is free to rotate along x,y and z axis and it is then saved as a transform matrix. In a case where the sequence of rotation is not known and the object is rotated for more than 3 times (eg :-if i rotate the object x-60degress, y-30 degrees, z-45 degrees then again x->30 degrees), is it possible to extract the angles rotated from the transform matrix?.I know that it is possible to get angles if the sequence of rotation is known, but if I have only the final transform matrix with me and nothing else, is it possible to get the angles rotated(x,y,and z) from the transform matrix ?
Euler angle conversion is a pretty well known topic. Just normalize the matrix orientation vectors and then use something like this c source code.
The matrix is the current state of things it has no knowledge of what the transformation has been in the past. It does not know how the matrix was built. You can just take the matrix into and decompose it into any pieces you like, as long as:
The data do not overlap. For example:Two X turns after each other is indistinguishable form each other (no way to know if its 1 2 or three different rotations summed).
The sequence order is known
A decomposition can be built out of the data (for example scale can be measured)
I am writing 3D app for OpenGL ES 2.0 where the user sets a path and flies over some terrain. It's basically a flight simulator on rails.
The path is defined by a series of points created from a spline. Every timeslice I advance the current position using interpolation i.e. I interpolate between p0 to p1, then when I reach p1 I interpolate between p1 and p2, then finally back from pN to p0.
I create a view matrix with something analogous to gluLookAt. The eye coord is the current position, the look at is the next position along the path and an up (0, 0, 1). So the camera looks towards where it is flying to next and Z points towards the sky.
But now I want to "bank" as I turn. i.e. the up vector is not necessarily directly straight up but a changes based on the rate of turn. I know my current direction and my last direction so I could increment or decrement the bank by some amount. The dot product would tell me the angle of turn, and the a cross product would tell me if its to the left or right. I could maintain a bank angle and keep it within the range -/+70 degrees, incrementing or decrementing appropriately.
I assume this is the correct approach but I could spend a long time implementing it to find out it isn't.
Am I on the right track and are there samples which demonstrate what I'm attempting to do?
Since you seem to have a nice smooth plane flying in normal conditions you don't need much... You are almost right in your approach and it will look totally natural. All you need is a cross product between 3 sequential points A, B, C: cross = cross(A-B, C-B). Now cross is the vector you need to turn the plane around the "forward" vector: Naturally the plane's up vector is (-gravitation) usually (0,0,1) and forward vector in point B is C-B (if no interpolation is needed) now "side" vector is side = normalized(cross(forward, up)) here is where you use the banking: side = side + cross*planeCorrectionParameter and then up = cross(normalized(side), normalized(forward)). "planeCorrectionParameter" is a parameter you should play with, in reality it would represent some combination of parameters such as dimensions of wings and hull, air density, gravity, speed, mass...
Note that some cross operations above might need swap in parameter order (cross(a,b) should be cross(b,a)) so play around a bit with that.
Your approach sounds correct but it will look unnatural. Take for example a path that looks like a sin function: The plane might be "going" to the left when it's actually going to the right.
I can mention two solutions to your problem. First, you can take the derivative of the spline. I'm assuming your spline is a f(t) function that returns a point (x, y, z). The derivative of a parametric curve is a vector that points to the rotation center: it'll point to the center of a circular path.
A couple of things to note with the above method: the derivative of a straight line is 0, and the vector will also be 0, so you have to fix the up vector manually. Also, you might want to fix this vector so it won't turn upside down.
That works and will look better than your method. But it will still look unnatural for some curves. The best method I can mention is quaternion interpolation, such as Slerp.
At each point of the curve, you also have a "right" vector: the vector that points to the right of the plane. From the curve and this vector, you can calculate the up vector at this point. Then, you use quaternion interpolation to interpolate the up vectors along the curve.
If position and rotation depends only on spline curvature the easiest way will be Numerical differentiation of 3D spline (you will have 2 derivatives one for vertical and one for horizontal components). Your UP and side will be normals to the tangent.