Is this Transform possible using a Matrix? - matrix

I'm trying to take a static list of vertices and, using a matrix, bend them about a circle as shown in the image below. I can find the new vertices using basic geometry, but I'm unsure how to implement it with a matrix, or if it is even possible. I believe, calling the center of the circle 'C' and calling the distance from the vertex to C 'd', that x' = Cx + d*cos(theta) and y' = Cy + d*sin(theta). (Cx and Cy are components of C). However, I don't think that that, in itself, can be converted to a matrix.
The Transformation
For context, I'm making a 3D Snake game. The Snake is made up of segments, and each segment should connect to the next. I have a direction and position for each connection between the segments, so I figured that I could build the segment by connecting each part as shown. However, it would be inefficient to calculate the vertices for each segment on each frame. If I could have the vertices statically listed and then transform it in the model-world matrix, that would be faster, and fit into the method I'm currently using. I included a simple drawing of the Snake (ignore the head) below.
The Snake
If it's not possible, are there any alternatives that can be done using a matrix while giving a similar result?

Yes, it is possible.
Skeleton Animation:
You can actually add a series of bones to the object and just apply rotation to the bones equally to get a perfect curve. This is the easiest way to achieve this. However, not necessarily the fastest way for your case.
Just Matrix & Weights:
If the bending is always in this proportion, you have to add weight information to each vertex and then multiply with a matrix with transformation/rotation/scale combination. This will give you better performance compared to Skeleton animation, as every vertex is multiplied using only one matrix and there is no hierarchy.

Related

Pose from essential matrix, the order of transform

From I've understood, the transform order (rotate first or translate first) yield different [R|t].
So I want to know what's the order of the 4 possible poses you got from essential matrix SVD.
I've read a code implementation of Pose From Essential Matrix(Hartley and Zisserman's multiple view geometry (page 259)). And the author seems to interpret it as rotate first then translate, where he retrieve camera position by using p = -R^T * t.
Also, opencv seems to use trasnlate first then rotate rule. Because the t vector I got from calibrating camera is the position of camera.
Or maybe I have been wrong and the order doesn't matter?
You shouldn't use SVD to decompose a transformation into rotation and translation components. Viewed as x' = M*x = T*R*x, the translation is just the fourth column of M, and the rotation is in the upper-left 3x3 submatrix.
If you feed the whole 4x4 matrix into SVD, I'm not sure what you'll get out, but it won't be useful. (If nothing else, U and V will not be affine.)

Method for finding all cubes of size L in a viewing frustum?

I am trying to find or search for a method that quickly finds all cubes of size L that would be contained by a viewing frustum. Maybe even using cuda.
I have made a DDA traversal for raycasting, which is like a 1D case to me and simple, as I only move along the line at a known distance.
My instinct was to create a bounding box of the frustum, and subdivide this space into a spatial grid of size L cubes. Then test each cell's center of the grid for being inside the frustum. Considering the frustum is a pyramid, it seems that about half the cells would be occupied by a bounding box and I feel that this method is just doing too much work. It will surely work though, I am hoping for a less naive or faster geometric approach.
Perhaps ray cast the left wall first, then right wall second and then line cast in between these? So in a nutshell, looking for the R3 version of something like a DDA traversal.
The fastest way to detect if a vertex resides within a frustum is dot product. The frustum consists of 4 planes, that is top, bottom, left, right, and two z values, front and back clipping. For each vertex check two things: First, is it outside front or back panel? And if not, is it inside the four planes?
To check if a vertex is outside front or back panel you check vertex.Z against your frustrum:
isInsideZ = vertex.Z >= frustrum.Zmin && vertex.Z <= frustrum.Zmax;
To check if it's inside the four frustrum 'walls' you need to compute the cross vectors for them, oriented towards the frustrum's center. Then check the dot product of each cross vector and the position vector to your vertex relative to the respective plane. You obtain this position vector by subtracting some arbitrary point on the plane from the vertex you test. Should the dot product be positive, the vertex is above that plane.
isAbove[i] = Vector3D.Dot(cross[i], vertex - planeloc[i]) > 0;
Where planeloc[i] is any point located on the respective plane i.
The vertex is inside the frustrum if all conditions are met:
isInside = isInsideZ && isAbove[0] && isAbove[1] && isAbove[2] && isAbove[3];
This sounds a bit awkward to handle, but a lot of things can be done outside the grinding loop, such as computing the cross products, i.e. frustrum plane normals, or the plane location vectors. For example, if a plane is spanned by (1,0,0), (1,1,0) then (1,0,0) already represents a point located on that plane.

Generating a 3D space filling Hilbert curve using turtle graphics

I have a turtle-graphics-based algorithm for generating a space-filling Hilbert curve in two dimensions. It is recursive and goes like this:
Wa want to draw a curve of order n, in direction x (where x ∈ {L, R}), and let y be the direction opposite to x. We do as follows:
turn in the direction y
draw a Hilbert curve of order n-1, direction y
move one step forward
turn in the direction x
draw a Hilbert curve of order n-1, direction x
move one step forward
draw a Hilbert curve of order n-1, direction x
turn in the direction x
move one step forward
draw a Hilbert curve of order n-1, direction y
I understand this and was able to implement a working solution. However, I'm now trying to "upgrade" this to 3D, and here's where I basically hit a wall; in 3D, when we reach a vertex, we can turn not in two, but four directions (going straight or backing up is obviously not an option, hence four and not six). Intuitively, I think I should store the plane on which the turtle is "walking" and its general direction in the world, represented by an enum with six values:
Up
Down
Left
Right
In (from the camera's perspective, it goes "inside" the world)
Out (same as above, outside)
The turtle, like in 2D, has a state containing the information outlined above, and when it reaches as vertex (which can be thought of as a "crossing") has to make a decision where to go next, based on that state. Whereas in two dimensions it is rather simple, in three, I'm stumped.
Is my approach correct? (i.e., is this what I should store in the turtle's state?)
If it is, how can I use that information to make a decision where to go next?
Because there are many variants of 3D space filling Hilbert curves, I should specify that this is what I'm using as reference and to aid my imagination:
I'm aware that a similar question has already been asked, but the accepted answer links to a website there this problem is solved using a different approach (i.e., not turtle graphics).
Your 2d algorithm can be summarized as “LRFL” or “RLFR” (with “F” being “forward”). Each letter means “turn that direction, draw a (n-1)-curve in that direction, and take a step forward”. (This assumes the x in step 8 should be a y.)
In 3d, you can summarize the algorithm as the 7 turns you would need to go along your reference. This will depend on how you visualize the turtle starting. If it starts at the empty circle, facing the filled circle, and being right-side-up (with its back facing up), then your reference would be “DLLUULL”.

How to find if a 3D object fits in another 3D object (the container)?

Given two 3d objects, how can I find if one fits inside the second (and find the location of the object in the container).
The object should be translated and rotated to fit the container - but not modified otherwise.
Additional complications:
The same situation - but look for the best fit solution, even if it's not a proper match (minimize the volume of the object that doesn't fit in the container)
Support for elastic objects - find the best fit while minimizing the "distortion" in the objects
This is a pretty general question - and I don't expect a complete solution.
Any pointers to relevant papers \ articles \ libraries \ tools would be useful
Here is one perhaps less than ideal method.
You could try fixing the position (in 3D space) of 1 shape. Placing the other shape on top of that shape. Then create links that connect one point in shape to a point in the other shape. Then simulate what happens when the links are pulled equally tight. Causing the point that isn't fixed to rotate and translate until it's stable.
If the fit is loose enough, you could use only 3 links (the bare minimum number of links for 3D) and try every possible combination. However, for tighter fit fits, you'll need more links, perhaps enough to place them on every point of the shape with the least number of points. Which means you'll some method to determine how to place the links, which is not trivial.
This seems like quite hard problem. Probable approach is to have some heuristic to suggest transformation and than check is it good one. If transformation moves object only slightly out of interior (e.g. on one part) than make slightly adjust to transformation and test it. If object is 'lot' out (e.g. on same/all axis on both sides) than make new heuristic guess.
Just an general idea for a heuristic. Make a rasterisation of an objects with same pixel size. It can be octree of an object volume. Make connectivity graph between pixels. Check subgraph isomorphism between graphs. If there is a subgraph than that position is for a testing.
This approach also supports 90deg rotation(s).
Some tests can be done even on graphs. If all volume neighbours of a subgraph are in larger graph, than object is in.
In general this is 'refined' boundary box approach.
Another solution is to project equal number of points on both objects and do a least squares best fit on the point sets. The point sets probably will not be ordered the same so iterating between the least squares best fit and a reordering of points so that the points on both objects are close to same order. The equation development for this is a lot of algebra but not conceptually complicated.
Consider one polygon(triangle) in the target object. For this polygon, find the equivalent polygon in the other geometry (source), ie. the length of the sides, angle between the edges, area should all be the same. If there's just one match, find the rigid transform matrix, that alters the vertices that way : X' = M*X. Since X' AND X are known for all the points on the matched polygons, this should be doable with linear algebra.
If you want a one-one mapping between the vertices of the polygon, traverse the edges of the polygons in the same order, and make a lookup table that maps each vertex one one poly to a vertex in another. If you have a half edge data structure of your 3d object that'll simplify this process a great deal.
If you find more than one matching polygon, traverse the source polygon from both the points, and keep matching their neighbouring polygons with the target polygons. Continue until one of them breaks, after which you can do the same steps as the one-match version.
There're more serious solutions that're listed here, but I think the method above will work as well.
What a juicy problem !. As is typical in computational geometry this problem
can be very complicated with a mismatched geometric abstraction. With all kinds of if-else cases etc.
But pick the right abstraction and the solution becomes trivial with few sub-cases.
Compute the Distance Transform of your shapes and Voilà! Your solution is trivial.
Allow me to elaborate.
The distance map of a shape on a grid (pixels) encodes the distance of the closest point on the
shape's border to that pixel. It can be computed in both directions outwards or inwards into the shape.
In this problem, the outward distance map suffices.
Step 1: Compute the distance map of both shapes D_S1, D_S2
Step 2: Subtract the distance maps. Diff = D_S1-D_S2
Step 3: if Diff has only positive values. Then your shapes can be contained in each other(+ve => S1 bigger than S2 -ve => S2 bigger than S1)
If the Diff has both positive and negative values, the shapes intersect.
There you have it. Enjoy !

How do I calculate the up vector in a flight simulator?

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.

Resources