I want to make a non-real time simulation of overlapping repulsive balls, initially in 2D and later in 3D.
First of all, consider a simple closed domain for simplicity. In practice, domains will be complex and irregular but always closed.
The balls on the boundaries are fixed and could be overlapping. A fixed ball duplicates itself to produce a free ball of the same size whenever no other ball overlaps it. Both fixed and free balls repel each other but fixed balls cannot move. Note that, duplicant ball should be sufficiently tilted to start repulsion. In elastic colliding balls case, after two balls collide they change direction with some velocity but in this case the balls can stop quickly once they stop overlapping. Free balls move until there is no motion or let's say we solve motion problem until convergence. Then each fixed ball produce a free ball again and this process goes on until no fixed ball can duplicate due to being overlapped by any other ball(s).
I think GPU (CUDA) would be faster to solve this problem but initially I am thinking to write on CPU. However, before proceeding to coding I would like to know "feasibility" of this work. That is, considering a million of balls, approximately how long it would take to simulate this or similar kind of problems in non-real time. For a million of balls, if solution time is in order of minutes, I will dive into the problem.
You might look into using Box2D for a prototype. Setting up your collision constraints to be 'soft' would give you about the kind of behavior you're showing in your diagrams.
As for simulating a million objects in real time, you're going to be working on a GPU.
Related
I have a physics engine that uses AABB testing to detect object collisions and an animation system that does not use linear interpolation. Because of this, my collisions act erratically at times, especially at high speeds. Here is a glaringly obvious problem in my system...
For the sake of demonstration, assume a frame in our animation system lasts 1 second and we are given the following scenario at frame 0.
At frame 1, the collision of the objects will not bet detected, because c1 will have traveled past c2 on the next draw.
Although I'm not using it, I have a bit of a grasp on how linear interpolation works because I have used linear extrapolation in this project in a different context. I'm wondering if linear interpolation will solve the problems I'm experiencing, or if I will need other methods as well.
There is a part of me that is confused about how linear interpolation is used in the context of animation. The idea is that we can achieve smooth animation at low frame rates. In the above scenario, we cannot simply just set c1 to be centered at x=3 in frame 1. In reality, they would have collided somewhere between frame 0 and frame 1. Does linear interpolation automatically take care of this and allow for precise AABB testing? If not, what will it solve and what other methods should I look into to achieve smooth and precise collision detection and animation?
The phenomenon you are experiencing is called tunnelling, and is a problem inherent to discrete collision detection architectures. You are correct in feeling that linear interpolation may have something to do with the solution as it can allow you to, within a margin of error (usually), predict the path of an object between frames, but this is just one piece of a much larger solution. The terminology I've seen associated with these types of solutions is "Continuous Collision Detection". The topic is large and gets quite complex, and there are books that discuss it, such as Real Time Collision Detection and other online resources.
So to answer your question: no, linear interpolation on its own won't solve your problems*. Unless you're only dealing with circles or spheres.
What to Start Thinking About
The way the solutions look and behave are dependant on your design decisions and are generally large. So just to point in the direction of the solution, the fundamental idea of continuous collision detection is to figure out: How far between the early frame and the later frame does the collision happen, and in what position and rotation are the two objects at this point. Then you must calculate the configuration the objects will be in at the later frame time in response to this. Things get very interesting addressing these problems for anything other than circles in two dimensions.
I haven't implemented this but I've seen described a solution where you march the two candidates forward between the frames, advancing their position with linear interpolation and their orientation with spherical linear interpolation and checking with discrete algorithms whether they're intersecting (Gilbert-Johnson-Keerthi Algorithm). From here you continue to apply discrete algorithms to get the smallest penetration depth (Expanding Polytope Algorithm) and pass that and the remaining time between the frames, along to a solver to get how the objects look at your later frame time. This doesn't give an analytic answer but I don't have knowledge of an analytic answer for generalized 2 or 3D cases.
If you don't want to go down this path, your best weapon in the fight against complexity is assumptions: If you can assume your high velocity objects can be represented as a point things get easier, if you can assume the orientation of the objects doesn't matter (circles, spheres) things get easier, and it keeps going and going. The topic is beyond interesting and I'm still on the path of learning it, but it has provided some of the most satisfying moments in my programming period. I hope these ideas get you on that path as well.
Edit: Since you specified you're working on a billiard game.
First we'll check whether discrete or continuous is needed
Is any amount of tunnelling acceptable in this game? Not in billiards
no.
What is the speed at which we will see tunnelling? Using a 0.0285m
radius for the ball (standard American) and a 0.01s physics step, we
get 2.85m/s as the minimum speed that collisions start giving bad
response. I'm not familiar with the speed of billiard balls but that
number feels too low.
So just checking on every frame if two of the balls are intersecting is not enough, but we don't need to go completely continuous. If we use interpolation to subdivide each frame we can increase the velocity needed to create incorrect behaviour: With 2 subdivisions we get 5.7m/s, which is still low; 3 subdivisions gives us 8.55m/s, which seems reasonable; and 4 gives us 11.4m/s which feels higher than I imagine billiard balls are moving. So how do we accomplish this?
Discrete Collisions with Frame Subdivisions using Linear Interpolation
Using subdivisions is expensive so it's worth putting time into candidate detection to use it only where needed. This is another problem with a bunch of fun solutions, and unfortunately out of scope of the question.
So you have two candidate circles which will very probably collide between the current frame and the next frame. So in pseudo code the algorithm looks like:
dt = 0.01
subdivisions = 4
circle1.next_position = circle1.position + (circle1.velocity * dt)
circle2.next_position = circle2.position + (circle2.velocity * dt)
for i from 0 to subdivisions:
temp_c1.position = interpolate(circle1.position, circle1.next_position, (i + 1) / subdivisions)
temp_c2.position = interpolate(circle2.position, circle2.next_position, (i + 1) / subdivisions)
if intersecting(temp_c1, temp_c2):
intersection confirmed
no intersection
Where the interpolate signature is interpolate(start, end, alpha)
So here you have interpolation being used to "move" the circles along the path they would take between the current and the next frame. On a confirmed intersection you can get the penetration depth and pass the delta time (dt / subdivisions), the two circles, the penetration depth and the collision points along to a resolution step that determines how they should respond to the collision.
I want to do a project, which will consist in detecting possible collision of the pool balls, using opencv, webcam and C++ programming language. For now I just want to prediction collision of 2 balls on minibilard table. I detect them by change rgb to hsv and then use thereshold, in future i will probably use another method for detect a random amount of balls, but it's not so important now.
So, for now I can detect two balls, i know their position, radius, now I'm thinking how to predict whether there will be a collision between them, if we if we assume that they will move in straight lines. I think that I should check their position in every frame update (and i have to know a time between frames in my webcamera) and by that, i I will be able to determine the value of speed, acceleration and direction of the ball. So, if i will know those parameters for for both balls, I will be able to determine where can they collide, and then, using parametric equastion I will be able to check, if they will be on collision point on the same time.
I wonder if this is the right approach to the problem, maybe there is a simpler and more effective method to do this?
Thanks for any kind of help.
Karol
This sounds like you are on track for a good project...
Calculating acceleration seems, from what I briefly read here, reasonably difficult though. So as a preliminary step, you could just assume a constant velocity. So take the difference between a balls position last frame and current frame as a vector and add it on to the current frames position to find where it will be next frame. Doing this for both balls will allow you to check for a collision.
You can check for a collision by comparing the distance between the balls centers using Pythagoras to the sum of their radii. If the sum of their radii will be greater than the distances between their centers, you have a collision.
Obviously, calculating one frame ahead is not very useful, but if you assume a constant velocity or manage to calculate their acceleration, there is no reason to why you can't calculate 30 or 100 frames in the future with this method.
I recently made a billiards ball simulation in javascript which you could take a quick look at here if you want to see how this could work.
I have a small application I have built where there are a few balls on a blank background. They all start flying through the air and use the physics I wrote to bounce accurately and have realistic collision responses. I am satisfied with how it looks except I have an issue where when my balls land directly on top of each other, the attach together and float directly up.
Here are the functions involved
https://gist.github.com/anonymous/899d6fb255a85d8f2102
Basically if the Collision function returns true, I use the ResolveCollision to change their velocities accordingly.
I believe the issue is from the slight re-positioning I do in ResolveCollision(). If they collide I bring them a frame or so backwards in location so that they are not intersecting still the next frame. However, when they are directly on top they bounce off eachother at such small bounces that eventually stepping back a frame isn't enough to unhook them.
I'm unsure if this is the problem and if it is, then what to do about it.
Any help would be awesome!
The trick is to ignore the collision if the circles are moving away from each other. This works so long as your timestep is small enough relative to their velocities (i.e. the circles can't pass through each other in a single frame).
When the circles first collide, you will adjust their velocity vectors so their relative velocity vector pushes them apart (because a collision will do that). After that, any further collisions are spurious because the circles will be moving apart, and will eventually separate completely. So, just ignore collisions between objects that are moving apart, and you should be fine.
(I've implemented such an algorithm in a 3D screensaver I wrote, but the algorithm is entirely dimension-agnostic and so would work fine for 2D circles).
I'm working on a Minecraft like game for educational purposes. The rendering is great so far even with 1024x1204 blocks but now that I started integrating the player collision I'm having problems.
I have a aabb for the player and aabb's for all the blocks around him. These are created dynamically and it works out pretty fast.
My problem goes as following:
I have speed vector and the current position. For each axis I calculate the potential position and make out an aabb. I check for collisions and it's free I move there otherwise I set the speed for that component to 0. I separate the axis since I want my player to slide in a direction of partially facing a wall.
The order for the axis is y,x,z. The collision response is great but I'm having some problems with the corners as it sometimes get's stuck in the world without being able to move. Not sure what the reason is for this.
I do not want to implement actual physics since those are more demanding and basically just too much for what I need.
Do you guys have any suggestions on how to implement this in a nice way? I did some searching but I didn't find anything useful for this particular situation.
This is a bit abstract in a sense that the cause of your problem can be related to many things. From the top of my head, maybe a bug in your collision detection code: somehow it allows the objects to cross boundaries by 1 (or more) unit. So when the next collision is computed 1 or more dimension is stuck (imagine having an arm already inside the wall when collision is detected. You can't get your arm out because it collide with the interior of the wall boundary)
I just want to do a simple animation (for example in C++ using OpenGL) of some moving object - let's say simple horizontal movement of a square from left to right.
In OpenGL, I can use "double-buffering" method and let's say a user (running my application with the animation) have turned "vertical sync" on - so I can call some function every time when a monitor refreshes itself (I can achieve that for example using Qt toolkit and its function "swapBuffers").
So, I think, the "smoothest" animation that I can achieve, is to "move the square by for example 1 pixel (can be other values) every time monitor refreshes", so at each "frame" the square is 1 pixel further - "I HAVE TESTED THIS, AND IT SURELY WORKS SMOOTHLY".
But the problem arises when I want to have "separate" thread for "game logic" (moving the square by 1 pixel to the right) and for "animation" (displaying current position of the square on the screen). Because let's say the game logic thread is a while loop where I move the square by 1 pixel and then "sleep" the thread for some time, for example 10 milliseconds, and my monitor refreshes for example every 16 milliseconds - the movement of the square "won't be 100% smooth" because sometimes the monitor will refresh two times where the square moves by only by 1 pixel and not by 2 pixels (because there two "different" frequencies of monitor and game logic thread) - and the movement will look "little jerky".
So, logically, I could stay with the first super smooth method, but, it cannot be used in for example "multiplayer" (for example "server-client") games - because different computers have different monitor frequencies (so I should use different threads for game logic (on the server) and for animation (on the clients) ).
So my question is:
Is there some method, using different threads for game logic and animation, which do "100% smooth" animation of some moving object and if some exists, please describe it here, or when I just had some "more complex scene to render", I just would not see that "little jerky movement" which I see now, when I move some simple square horizontally, and I deeply concentrate on it :) ?
Well, this is actually typical separate game-loop behavior. You manage all you physics (movement) related actions in one thread, letting the render thread to do its work. This is actually desirable.
Don´t forget this way of implementation of game loop is to have maximum available frame rate while preserving constant physics speed. At higher FPS, you can not see this effect by any chance, if there is not any other code related problem. Some hooking between framerate and physics for example.
If you want to achieve what you describe as perfect smoothness, you could synchronize your physics engine with VSync. Simply do all your physics BEFORE refresh kicks in, than wait for another.
But this all applies to constant speed objects. If you have object with dynamic speed, you can never know when to draw it to be "in sync". Same problem arises then you want multiple object with different constant speeds.
Also, this is NOT what you want in complex scenes. The whole idea of V-sync is to limit screen tearing effect. You should definitely NOT hook your physics or rendering code to display refresh rate. You want you physics code to run independent of users display refresh rate. This could be REAL pain in multiplayer games for example. For start, look at this page: How A Game Loop Works
EDIT:
I say your vision of perfect smoothness is unrealistic. You can mask it using techniques Kevin wrote. But you will always struggle with HW limits as refresh rate, or display pixelation. For example, you have window of 640x480 px. Now, you want your object to move horizontally. You can move your object by vector heading towards bottom right corner, BUT you must increment object coordinates by float number (640/480). But in rendering, you go to integers. So your object moves jagged. No way around this. In small speed, you can notice it. You can blur it, or make it move faster, but never get rid of it...
Allow your object to move by fractions of a pixel. In OpenGL, this can be done for your example of a square by drawing the square onto a texture (i.e. a one-pixel or larger border), rather than letting it be just the polygon edge. If you are rendering 2D sprite graphics, then you get this pretty much automatically (but if you have 1:1 pixel art it will be blurred/sharp/blurred as it crosses pixel boundaries).
Smooth (antialias) the polygon edge (GL_POLYGON_SMOOTH). The problem with this technique is that it does not work with Z-buffer-based rendering since it causes transparency, but if you are doing a 2D scene you can make sure to always draw back-to-front.
Enable multisample/supersample antialiasing, which is more expensive but doesn't have the above problem.
Make your object have a sufficiently animated appearance that the pixel shifts aren't easy to notice because there's much more going on at that edge (i.e. it is itself moving in place at much more than 1 pixel/frame).
Make your game sufficiently complex and engrossing that players are distracted from looking at the pixels. :)