I'm working on a 3D tile based game and I'm using AABB collision detection. For every cube that the player is intersecting, I find the axis along which the player is intersecting the cube the least, and push the player out of the cube along that axis.
Depending on the order that the cubes are checked in, this can cause problems when sliding along the edge of multiple cubes. I have created a diagram that should explain the problem:
http://imgur.com/mmK0W.png
Arrow #1 is the attempted movement of the player. The other arrows are the collision response.
In the left diagram, collision is tested against the right cube first, causing the player to be pushed to the left, and then upwards. (bad)
In the right diagram, collision is tested against the left cube first, causing the player to be pushed upwards, at which point the player is no longer intersecting the other cube. (good)
Any ideas on what the most efficient way to solve this might be? Or any better ways to handle the collision response?
Thank you.
A discrete implementation forces you to inject some continuous math in the system, only when required (cubes / directions overlap).
For each cube c1, c2 ... ci with which the user cube (uc) intersects at the time of the check, you want to find out which cube was "touched" first - there is only one, as in real life. Consider the direction d of uc, and, taking the amount of uc in ci (overlapping) find the position of cu at the time it "touched" ci.
Determine which cube was "touched" first cj (the one that required the most rollback on the d axis - the sooner in time) and use only this one to calculate the collision reaction.
Not only you'll reach accuracy. but it will help if all cubes are moving, have different speeds etc...
From your diagram, it seems you want the smallest move that minimises the overlap between the player and the cubes. Each cube with overlap will try to "push" the player in two orthogonal directions. Can you do something like pick the minimum push of the maximum pushes in each direction?
You might implement a kind of hybrid broad phase when your two (or more) stationary cubes in a row can be combined into one larger rectangle. Test against the larger rectangle first. It will give you the results of your green check mark and be faster than checking each cube anyway. Then, after that, only if you need to, check against the individual cubes.
A collision can push an object on 1 axis only. To determine the axis to push:
else -- not this
elseif -- change to this
if w > h then
push x
elseif h > w then
push y
end
This works if your tiles are aligned.
Use circles to avoid the stick on unaligned tiles
Related
As the title suggest my problem lies in some representation of a sphere surface in computer memory. For simplicity, let's say we are making a chess game where the board is on a sphere. If the board was a classic flat board, then the solution is simple: use a 2D table.
But I don't know what kind of a memory structure I should chose for a sphere. Namely, what I want from this representation are:
If I move a pawn stubbornly in one direction, then I should return to the point where I started,
During such "journey" I should cross a point directly on the other side of the sphere (I mean to avoid a common "error" in a 2D game where moving pass an edge of a board will move an object to the opposite edge, thus making the board a torus, not a real sphere)
the area of one board cell should be approximately equal to any other cell
a cell should have got an associated longitude-latitude coordinates (I wrote "associated" because I want from the representation to only have got some way to obtain these coordinates from the position of a cell, not to be eg. a table with lat-long indexes)
There's no simple geometric solution to this. The crux of the problem is that, say you have n columns at the equator, and you're currently near the north poll, and heading north. Then the combination of the direction and the column number from the top row (and second from top row) must be able to uniquely identify which one of the n positions at the equator that path is going to cross. Therefore, direction could not be an integer unless you have n columns in the top (or second to top) row. Notice that if the polygons have more than three sides, then they must have common edges (and triangles won't work for other reasons). So now you have a grid, but if you have more than three rows (i.e. a cube, or other regular prism), then moving sideways on the second-to-top row will not navigate you to the southern hemisphere.
The best bet might be to create a regular polyhedron, and keep the point and direction as floating point vectors/points, and calculate the actual position when you move, and figure out which polygon you land in (note, you would have the possibility of moving to non-adjacent polygons with this method, and you might have issues if you land exactly on an edge/vertex, etc).
I am trying to write a Rigid body simulator, and during simulation, I am not only interested in finding whether two objects collide or not, but also the point as well as normal of collision. I have found lots of resources which actually says whether two OBB are colliding or not using separating axis theorem. Also I am interested in 3D representation of OBB. Now, if I know the axis with minimum overlap region for two colliding OBB, is there any way to find the point of collision and normal of collision? Also, there are two major cases of collision, first, point-face and second edge-edge.
I tried to google this problem, but almost every solution is only detecting collision with true or false.
Kindly somebody help!
Look at the scene in the direction of the motion (in other terms, apply a change of coordinates such that this direction becomes vertical, and drop the altitude). You get a 2D figure.
Considering the faces of the two boxes that face each other, you will see two hexagons each split in three parallelograms.
Then
Detect the intersections between the edges in 2D. From the section ratios along the edges, you can determine the actual z distances.
For all vertices, determine the face they fall on in the other box; and from the 3D equations, the piercing point of the viewing line into the face plane, hence the distance. (Repeat this for the vertices of A and B.)
Comparing the distances will tell you which collision happens first and give you the coordinates of the first meeting point (in the transformed system, the back to absolute coordinates).
The point-in-face problem is easy to implement as the facesare convex polygons.
I'm working on a problem. I want to efficiently tile a polygon.
The polygon is random. It could be literally any shape from a triangle (# of sides = 3) to a circle (# of sides = infinity). It could be concave or convex.
All tiles are fixed size rectangles.
All tiles will have the same orientation.
If it makes the conversation easier, we can use squares as the tile shape.
Tiles are oriented parallel/perpendicular to the longest leg of the polygon, where ever that is.
I'm running in JavaScript on the browser, and I'm only using one polygon. In fact, the polygon is generated manually by a user.
I don't need crazy high packing efficiency, but reasonable performance to tile the polygon. (I'm not looking for an NP-hard solution here..)
I will only be filling one polygon, and I doubt the tile count would ever exceed 100.
I've found an excellent reference to test polygon to polygon interference. Code gleamed from this posting, written by Paul Bourke.
The general intersection test between two polygons is as follows:
/*
Return FALSE if two polygon intersect.
Polygon p1[] is of length n1 and polygon p2[] is of length n2.
Polygons are define with vertices ordered clockwise.
*/
int PolygonPolygon(XY *p1,XY *p2,int n1,int n2)
{
int i,j;
// Reject if a vertex of p1 is inside p2, And visa versa
for (i=0;i<n2;i++) {
if (InsidePolygon(p1,n1,p2[i]))
return(FALSE);
}
for (i=0;i<n1;i++) {
if (InsidePolygon(p2,n2,p1[i]))
return(FALSE);
}
// Reject any intersecting edges
for (j=0;j<n1;j++) {
for (i=0;i<n2;i++) {
if (LineIntersect(p1[j].x,p1[j].y,p1[(j+1)%n1].x,p1[(j+1)%n1].y,
p2[i].x,p2[i].y,p2[(i+1)%n2].x,p2[(i+1)%n2].y))
return(FALSE);
}
}
return(TRUE);
}
The supporting functions for these tests are given here: LineIntersect.c and here: InsidePolygon.c. (Update: Obviously I will have to modify these three functions a bit to look if the tile is either fully OUTSIDE of the polygon or with intersecting a polygon edge. Apologies for leaving that out initially... It goes without saying I have to convert them to JavaScript as well.)
My questions here relate to a reasonable algorithm to do the tiling.
Method 1 (the blind leading the blind)
go to upper left hand corner of the polygon's outer bounds. Grid layout with the tiles until the all bounds are covered with a tile. Test for interference, or out of bounds.
if interference, remove the tile.
I do have to modify the intersection test for this method to include the test "Are all four vertices of the tile located outside of the polygon?" If so, delete that tile.
Method 2 (slide it till it stops)
Select a point at center of mass to the bounds of the polygon.
Center a tile there. Test for interference.
If interference, grab another random point XYZ distance away from center of mass, try again. Attempt X more times at different orientations, if fail, increase radius y more times and try again. If totally no go, sigh, and prompt the user to click the mouse in the largest open area within the polygon.
From that point, slide towards the center of longest leg of the polygon, the one that sets the tile's angular orientation. Increment, test, increment test. At some point the tile will hit something. Slide the tile to "*bottom left" it hits something else. Stop. From there tile the rest of the polygon till you hit the bounds. Delete all tiles that are outside of polygon or interfere with the polygon's boundary.
My gut says method 2 will generate better results, but then there's this use case:
I've done a lot of reviews on bin packing, but because the polygon shape is so odd, they don't really seem to fit. Here's a great reference, Solving the 2D Packing Problem by Rod Stephens There is a whole lot of stuff on tile / packing a rectangle, not much at all on packing a polygon.
Is there a better algorithm? Are there holes in either of my two algorithms? Anybody been here before? Many thanks.
Edit: I received a comment asking for an image showing a desired output. As I was preparing a solution I realized a few errors in my original stated question (involving the interference tests required). I've added a desired output image with labeled tiles to ease whatever conversation is coming next. I also realize I should probably add a third method.
Method #3, One strip at a time. Slide and check.
start at left hand side of longest leg of the polygon. Add a tile, see if it fits, if interference, slide it "right" until there is no interference.
Add more tiles to finish the row.
Start the next row immediately above the start row. Push the tile as far "left" as it will go.
Add more tiles to finish the row.
Continue to add rows, slide left, then slide right.
There was a real trick on the top row of the example shown. The surprise was tiles #11 and #12 I think that adds a modification that is... when the end of the row hits, you should continue an incremental slide and retest until you reach the outer bounds of the polygon.
A proposed completed solution:
Note: I don't have an method that would work to identify tile #13 unless it just fit in method one using blind luck.
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”.
I've asked some questions here and seen this geometric shape mentioned a few times among other geodesic shapes, but I'm curious how exactly would I generate one about a point xyz?
There's a tutorial here.
The essential idea is to start with an icosahedron (which has 20 triangular faces) and to repeatedly subdivide each triangular face into smaller triangles. At each stage, each new point is shifted radially so it is the correct distance from the centre.
The number of stages will determine how many triangles are generated and hence how close the resulting mesh will be to a sphere.
Here is one reference that I've used for subdivided icosahedrons, based on the OpenGL Red Book. The BSD-licensed source code to my iPhone application Molecules contains code for generating simple icosahedrons and loading them into a vertex buffer object for OpenGL ES. I haven't yet incorporated subdivision to improve the quality of the rendering, but it's in my plans.
To tesselate a sphere, most people sub-divide the points linearly, but that does not produce a rounded shape.
For a rounded tesselation, rotate the two points through a series of rotations.
Rotate the second point around z (by the z angle of point 1) to 0
Rotate the second point around y (by the y angle of point 1) to 0 (this logically puts point 1 at the north pole).
Rotate the second point around z to 0 (this logically puts point 1 on the x/y plane, which now becomes a unit circle).
Find the half-angle, compute x and y for the new 3rd point, point 3.
Perform the counter-rotations in the reverse order for steps 3), 2) and 1) to position the 3rd point to its destination.
There are also some mathematical considerations for values near each of the near-0 locations, such as the north and south pole, and the right-most and left-most, and fore-most and aft-most positions, so check those first and perform an additional rotation by pi/4 (45 degrees) if they're at those locations. This prevents floating point math libraries from freaking out and producing wildly out-of-character values for atan2() and other trig functions.
Hope this helps! :-)