I'm running a very simple particle simulation where I move particles around in space.
Particles are represented as simple 3D points in space, and their movement is achieved by incrementing their position with a velocity vector (newPos = oldPos + velocity).
I'd like to introduce a form of collision detection where particles can bounce off 3d triangles (simple surfaces defined by three 3D points). A naive approach is to just shoot a ray off each particle in the direction of their velocity vector, with a length of the velocity magnitude of the particle, and if a ray-triangle intersection is detected, go from there to calculate particle reflection vector, etc.
However...if both particles and triangles are moving over time, there are lots of cases where collisions should occur, but that naive approach will fail to detect them. For example, imagine a slow moving particle approaching a fast moving triangle. At a particular simulation step the ray shot out of the particle along its trajectory may not reach a triangle ahead of it...but by the next simulation step the triangle might move so fast that it moves behind the particle and the collision is missed.
Is there a standard way to detect point-triangle collisions that can account for these types of problematic cases? Increasing simulation substeps is of course an option, but not a preferred one since it merely reduces the possibility of a missed collision, rather than preventing them entirely.
Related
I've started to write a physics engine but became stuck on some physics of resolving collisions. Let's say I have this situation:
I.e. body B is going towards body A at the speed of 1 space units/time unit. Both A and B have the same mass of 1 unit. Let's consider a completely elastic collision.
I've read in a book (Game Physics Engine Development) that an impulse-based approach can be used to resolve the collision (i.e. find out the linear and angular velocities of both bodies after the collision). As I understand it, it should work like this:
When the bodies collide, I get the point of the collision and the collision normal.
At the point of the collision I consider only two points colliding in the direction of the normal (the points at which the bodies are touching, i.e. I ignore the shapes of both bodies) and I compute the new velocities of these two colliding points (this is easy to do, there is a simple formula found e.g. on Wikipedia).
I find an impulse such that when applied to both bodies at this point it achieves the computed velocities for these two points.
Now the problem arises when I consider that from a physical point of view both momentum and kinetic energy need to be conserved. With these constraints in mind there is seemingly no solution, because:
When B collides with A, B should come to complete stop and transfer all its momentum and kinetic energy to A, according to elastic collision formula. In order for linear momentum to stay conserved, A then has to start linearly moving left at the same speed as B was before the collision (as they have the same mass). So now A has the same kinetic energy as B had, which however means that A cannot come into rotation because that would add additional kinetic energy to it (as rotating adds kinetic energy as well as linear motion), breaking the conservation of kinetic energy. Nevertheless, the physically correct solution IS for A to both move linearly to the left AND rotate as B colliding at this location exerts torque (and I've also checked real life object behave this way). Note that we cannot take away some energy of A's linear motion and add it to the rotation as that breaks the conservation of linear momentum.
The only "real" solution is that B doesn't come to complete stop and keeps some momentum while A will be both moving left and rotating. But this doesn't seem to be doable with the impulse-based approach that only takes into account the two colliding points, the elastic collision formula simply say the point at B should come to stop and as B cannot receive any torque (the collision happens in its middle), the only way to fulfill this is for B to stop moving.
So is there something I missed? Is the impulse-based approach just not physically correct? I appreciate any insight and suggestions on how to correctly resolve the collision. Thanks!
The formulas that you're looking at are for the collision of two point masses. Point masses can't have angular momentum, and so the formulas have no room for that term.
You have to go back to first principles.
Suppose that an edge collides with another body at a point (think corner hitting an edge). Then a specific impulse is imparted at that point, in a direction normal to the edge. (Any other direction would have required friction, which would make this a non-elastic collision.) The opposite impulse is imparted to the other body, along the same vector. Imparting opposite impulses to both bodies is sufficient to guarantee both conservation of momentum and angular momentum. But conservation of energy is going to take some work.
Next, what happens when we impart that momentum? As this physics answer says, we impart momentum as if the impulse happened to the center of mass. We impart angular momentum equal to the cross product of the impulse and the moment arm (the vector describing how much the impulse misses the center of mass). This will cause the body to start rotating at a rate of the impulse divided by the moment of inertia.
You get kinetic energy from the motion of the center of mass, but also kinetic energy from its rotation.
So in your 2-D collision you now have the following facts:
The mass of each body.
The velocities of each body.
The moment of inertia of each velocity.
The angular velocity of each body.
The moment arm of the line of force for each body.
You can now calculate the kinetic energy of the whole system, as a function of the magnitude of the specific impulse. Unlike the point mass, ALL of these factors play into it, making the equation complicated. However, like the point mass, you'll get a quadratic equation with 2 solutions. One solution is 0 impulse imparted (representing the system before the collision), and the other is your answer afterwards. Complete with changes to the momentum and angular momentum of both systems.
I'm trying to optimally fill a 3D spherical volume with "particles" (represented by 3D XYZ vectors) that need to maintain a specific distance from each other, while attempting to minimize the amount of free space present in-between them.
There's one catch though- The particles themselves may fall on the boundary of the spherical volume- they just can't exist outside of it. Ideally, I'd like to maximize the number of particles that fall on this boundary (which makes this a kind of spherical packing problem, I suppose) and then fill the rest of the volume inwards.
Are there any kinds of algorithms out there that can solve this sort of thing? It doesn't need to be exact, but the key here is that the density of the final solution needs to be reasonably accurate (+/- ~5% of a "perfect" solution).
There is not a single formula which fills a sphere optimally with n spheres. On this wikipedia page you can see the optimal configurations for n <= 12. For the optimal configurations for n <= 500 you can view this site. As you can see on these sites different numbers of spheres have different optimal symmetry groups.
your constraints are a bit vague so hard to say for sure but I would try field approach for this. First see:
Computational complexity and shape nesting
Path generation for non-intersecting disc movement on a plane
How to implement a constraint solver for 2-D geometry?
and sub-links where you can find some examples of this approach.
Now the algo:
place N particles randomly inside sphere
N should be safely low so it is smaller then your solution particles count.
start field simulation
so use your solution rules to create attractive and repulsive forces and drive your particles via Newton D'Alembert physics. Do not forget to add friction (so movement will stop after time) and sphere volume boundary.
stop when your particles stop moving
so if max(|particles_velocity|)<threshold stop.
now check if all particles are correctly placed
not breaking any of your rules. If yes then remember this placement as solution and try again from #1 with N+1 particles. If not stop and use last correct solution.
To speed this up you can add more particles instead of using (N+1) similarly to binary search (add 32 particles until you can ... then just 16 ... ). Also you do not need to use random locations in #1 for the other runs. you can let the other particles start positions where they were placed in last run solution.
How to determine accuracy of the solution is entirely different matter. As you did not provide exact rules then we can only guess. I would try to estimate ideal particle density and compute the ideal particle count based on sphere volume. You can use this also for the initial guess of N and then compare with the final N.
What is a fast algorithm for determining whether or not a point is inside a 3D mesh? For simplicity you can assume the mesh is all triangles and has no holes.
What I know so far is that one popular way of determining whether or not a ray has crossed a mesh is to count the number of ray/triangle intersections. It has to be fast because I am using it for a haptic medical simulation. So I cannot test all of the triangles for ray intersection. I need some kind of hashing or tree data structure to store the triangles in to help determine which triangle are relevant.
Also, I know that if I have any arbitrary 2D projection of the vertices, a simple point/triangle intersection test is all necessary. However, I'd still need to know which triangles are relevant and, in addition, which triangles lie in front of a the point and only test those triangles.
I solved my own problem. Basically, I take an arbitrary 2D projection (throw out one of the coordinates), and hash the AABBs (Axis Aligned Bounding Boxes) of the triangles to a 2D array. (A set of 3D cubes as mentioned by titus is overkill, as it only gives you a constant factor speedup.) Use the 2D array and the 2D projection of the point you are testing to get a small set of triangles, which you do a 3D ray/triangle intersection test on (see Intersections of Rays, Segments, Planes and Triangles in 3D) and count the number of triangles the ray intersection where the z-coordinate (the coordinate thrown out) is greater than the z-coordinate of the point. An even number of intersections means it is outside the mesh. An odd number of intersections means it is inside the mesh. This method is not only fast, but very easy to implement (which is exactly what I was looking for).
This is algorithm is efficient only if you have many queries to justify the time for constructing the data structure.
Divide the space into cubes of equal size (we'll figure out the size later). For each cube know which triangles has at least a point in it. Discard the cubes that don't contain anything. Do a ray casting algorithm as presented on wikipedia, but instead o testing if the line intersects each triangle, get all the cubes that intersect with the line, and then do ray casting only with the triangles in these cubes. Watch out not to test the same triangle more than one time because it is present in two cubes.
Finding the proper cube size is tricky, it shouldn't be neither to big or too small. It can only be found by trial and error.
Let's say number of cubes is c and number of triangles is t.
The mean number of triangles in a cube is t/c
k is mean number of cubes that intersect the ray
line-cube intersections + line-triangle intersection in those cubes has to be minimal
c+k*t/c=minimal => c=sqrt(t*k)
You'll have to test out values for the size of the cubes until c=sqrt(t*k) is true
A good starting guess for the size of the cube would be sqrt(mesh width)
To have some perspective, for 1M triangles you'll test on the order of 1k intersections
Ray Triangle Intersection appears to be a good algorithm when it comes to accuracy. The Wiki has some more algorithms. I am linking it here, but you might have seen this already.
Can you, perhaps improvise by, maintaining a matrix of relationship between the points and the plane to which they make the vertices? This subject appears to be a topic of investigation in the academia. Not sure how to access more discussions related to this.
Imagine we have a 2D sky (10000x10000 coordinates). Anywhere on this sky we can have an aircraft, identified by its position (x, y). Any aircraft can start moving to another coordinates (in straight line).
There is a single component that manages all this positioning and movement. When a aircraft wants to move, it send it a message in the form of (start_pos, speed, end_pos). How can I tell in the component, when one aircraft will move in the line of sight of another (each aircraft has this as a property as radius of sight) in order to notify it. Note that many aircrafts can be moving at the same time. Also, this algorithm is good to be effective sa it can handle ~1000 planes.
If there is some constraint, that is limiting your solution - it can probably be removed. The problem is not fixed.
Use a line to represent the flight path.
Convert each line to a rectangle embracing it. The width of the rectangle is determined by your definition of "close" (The bigger the safety distance is, the wider the rectangle should be).
For each new flight plan:
Check if the new rectangle intersects with another rectangle.
If so, calculate when will each plane reach the collision point. If the time difference is too small (and you should define too small according to the scenario), refuse the new flight plan.
If you want to deal with the temporal aspect (i.e. dealing with the fact that the aircraft move), then I think a potentially simplification is lifting the problem by the time dimension (adding one more dimension - hence, the original problem, being 2D, becomes a 3D problem).
Then, the problem becomes a matter of finding the point where a line intersects a (tilted) cylinder. Finding all possible intersections would then be n^2; not too sure if that is efficient enough.
See Wikipedia:Quadtree for a data structure that will make it easy to find which airplanes are close to a given airplane. It will save you from doing O(N^2) tests for closeness.
You have good answers, I'll comment only on one aspect and probably not correctly
you say that you aircrafts move in form (start_pos, speed, end_pos)
if all aircrafts have such, let's call them, flightplans then you should be able to calculate directly when and where they will be within certain distance from each other, or when will they be at closest point from each other or if the will collide/get too near
So, if they indeed move according to the flightplans and do not deviate from them your problem is deterministic - it boils down to solving a set of equations, which for ~1000 planes is not such a big task.
If you do need to solve these equations faster you can employ the techniques described in other answers
using efficient structures that can speedup calculating distances (quadtree, octree, kd-trees),
splitting the problem to solve the equations only for some relevant future timeslice
prioritize solving equations for pairs for which the distance changes most rapidly
Of course converting time to a third dimension turns the aircrafts from points into lines and you end up searching for the closest points between two 3d lines (here's some math)
I actually found an answer to this question.
It is in the book Real-Time Collision Detection, p. 223. It's better named, as well: Intersecting Moving Sphere Against Sphere, where a 2D sphere is a circle. It's not so simple (and I may also violate some rights) to explain it here, but the basic idea is to fix one of the circles as a point, adding its radius to the radius of the moving one. The new direction for the moving one is the sum of the two original vectors.
I have a 3D polygon mesh and a corresponding 2D polygon mesh (actually from a UV map) which I'm using to map the geometry onto a 2D plane. Given a point on the plane, how can I efficiently find the polygon on which it's resting in order to map that 2D point back into 3D?
The best approach I can think of is to store the polygons in a 2D interval tree, and use that to get candidate polygons. Is there a simpler approach?
To clarify, this is not for a shader. I'm actually taking a 2D physical simulation and rendering it wrapped around a 3D mesh. For drawing each object, I need to figure out what point in 3D corresponds to its real 2D position.*
One approach I've seen for triangle meshes goes as follows: choose a triangle, and imagine that each of the sides defines a half space. For a given edge, the half space boundary is the line containing the edge, and the half space does not contain the triangle. Choose an edge whose corresponding half space contains your target point. Then select the triangle on the other side of edge, and repeat the process.
Using this method, you will eventually end up at the triangle that contains your target point.
This method is arguable simpler than implementing a 2D interval tree, although the search is less efficient (if n is the number of triangles, it is O(√n) rather than O(log n). Also, it should work for a polygon mesh, as long as the polygons are convex.
So, if I were trying to just get the thing implemented, I'd probably start with a global search of all triangles - compute the barycentric coordinates of that 2d point for each triangle, find the triangle where the barycentric coordinates are all positive, and then use those to map to 3d (multiply the stu position by the 3d points). I'd do this first, and only if it's not fast enough would I try something more complex.
If it's possible to iterate by triangle rather than by 2d points, then the barycentric method would probably be fast enough. But it seems like you've got a bunch of 2d points at arbitrary positions that need to be mapped, and the points change position from frame to frame?
If you've got this kind of situation, you could probably get a big speedup by implementing a local update per frame. Each 2d point would remember which triangle it was within. Set that as the current triangle. Test if the new position is within the current triangle. If not, then you want to walk the mesh to the adjacent triangle which is closest to the target 2d point. Each edge-adjacent triangle is composed of the two common points on the edge, plus another point. Find which edge-adjacent triangle's other point is closest to the target, and set that as current. Then iterate - seems like it should find it pretty quickly? You could also cache a max size for each triangle, so if the point has moved a lot you can just iterate to the next neighbor without doing the barycentric computation (the max size would need to be the distance such that if you are farther than that distance from any triangle point there is no chance you're inside the triangle. This is the length of the largest edge).
But as you mention in your comments, you can run into problems with meshes that have concavities, holes, or separate connected components, where you may fall into a local minimum. There are a couple of ways to deal with this. I think the simplest is to keep a list of all visited triangles (maybe as a flag on the triangle, vector< bool > or set< triangle index >) and refuse to revisit a triangle. If you find that you've visited all the neighbors of your current triangle, then fall back to a global search. Such failures are likely to be uncommon, so it shouldn't hurt your performance too much.
This kind of per-frame updating can be very fast, and might even be a decent approach for computing the initial containing triangles - just choose a random triangle and walk from there (changes from checking all n triangles to only those that are in roughly a straight line to the target). If it's not fast enough, what you could do is keep a k-d tree (or something similar) of the 2d mesh points as well as a single touching triangle index for each mesh point. To seed the iteration, find the closest point to the target 2d point in the k-d tree, set the adjacent triangle to be current, and then iterate.