Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » I'm Just so Close (more Physics)

This thread is locked; no one can reply to it. rss feed Print
 1   2 
I'm Just so Close (more Physics)
Stas B.
Member #9,615
March 2008

I have a ready static implementation of SAT.
It's neat and clean and is just about 70 lines of code.
I can give it to you if you need it. It handles polygons, lines and points.
You'll have to figure out how to make it dynamic by yourself, though.
(I mean, not completely by yourself, there's plenty of info. and I can help out here and there, but I'm not gonna write it for you. xD)

1VECTOR poly_interval_on_axis(VECTOR poly[], int n, VECTOR axis)
2{
3 int i;
4 double temp;
5 VECTOR interval;
6 
7 interval.x = interval.y = VECTOR_DOT_PRODUCT(axis, poly[0]);
8 
9 for(i = 1; i < n; i++)
10 {
11 temp = VECTOR_DOT_PRODUCT(axis, poly<i>);
12 
13 if(temp < interval.x) { interval.x = temp; }
14 if(temp > interval.y) { interval.y = temp; }
15 }
16 
17 return interval;
18}
19 
20int intervals_intersect(VECTOR int0, VECTOR int1, double *depth)
21{
22 double d0, d1;
23 
24 if(int0.x > int1.y || int1.x > int0.y)
25 return 0;
26 
27 d0 = int0.y - int1.x;
28 d1 = int1.y - int0.x;
29 
30 *depth = (d0 < d1) ? -d0 : d1;
31 return 1;
32}
33 
34int poly_intersection_test(VECTOR a[], VECTOR b[], VECTOR an[], VECTOR bn[], int n0, int n1, VECTOR *mtd, VECTOR *n)
35{
36 VECTOR axis;
37 double depth, min_depth = 10000000.0;
38 int i, k;
39 
40 for(i = 0; i < n0; i++)
41 {
42 if(!intervals_intersect(poly_interval_on_axis(a, n0, an<i>), poly_interval_on_axis(b, n1, an<i>), &depth))
43 return 0;
44 
45 if(fabs(depth) < fabs(min_depth))
46 {
47 min_depth = depth;
48 k = i;
49 }
50 }
51 
52 for(i = 0; i < n1; i++)
53 {
54 if(!intervals_intersect(poly_interval_on_axis(a, n0, bn<i>), poly_interval_on_axis(b, n1, bn<i>), &depth))
55 return 0;
56 
57 if(fabs(depth) < fabs(min_depth))
58 {
59 min_depth = depth;
60 k = n0 + i;
61 }
62 }
63 
64 if(k < n0)
65 {
66 *mtd = USCALE_VECTOR(an[k], min_depth);
67 *n = an[k];
68 }
69 
70 else
71 {
72 *mtd = USCALE_VECTOR(bn[k - n0], min_depth);
73 *n = bn[k - n0];
74 }
75 
76 return 1;
77}

Anomie
Member #9,403
January 2008
avatar

Could I bother you for a few comments? like...
interval.x = interval.y = VECTOR_DOT_PRODUCT(axis, poly[0]);
Doesn't really make much sense to me. I mean, I know what it does, but not why it does it. (some of the naming isn't too obvious, not that it needs to be, but...)

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

Umm... You know how projection works, right? What I do there is to basically smash a polygon against an axis. I project every point using the dot product, and the result of the dot product is some value... Now, I find the minimum and maximum and that's the interval of the polygon on an axis. (The 'x' there is the minimum, the 'y' is the maximum. That's stupid, I know. ;D)
And what the hell do we need the intervals for?
Well, we project both objects on the same axis, check if the intervals overlap. If they do, we go on and check the next axis. If they don't, the objects can't possibly intersect.
The axes we need to check are actually the normals of the objects.
For the sake of illustration, I chose a random axis in the picture.
You can see on the right that the intervals overlap on that axis, but they don't intersect, so there must be another axis on which they don't overlap.

{"name":"satgb8.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/f\/4f0defde056eec6feb1c754cf233dea3.png","w":706,"h":269,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/f\/4f0defde056eec6feb1c754cf233dea3"}satgb8.png

[EDIT]

As for how dynamic SAT works...
Imagine a moving line checked against another line... You can draw lines between the old and new points of the line, and you get a quad, right?
If that quad intersects the other line, we have a collision forward in time!
So basically, it's just the same old, but with one extra axis to check: The velocity.

{"name":"dynfs9.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/2\/92000938028336e60ab953d375cf379a.png","w":273,"h":249,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/2\/92000938028336e60ab953d375cf379a"}dynfs9.png

So why only one extra axis if we have a whole quad now to check?
Because every normal of every side of a polygon is an axis, but the normals of parallel sides are the same, so we have 3 new sides formed, but the 'v' segments are parallel so there's actually just one new axis to check for, and the other side is parallel to the original line.

I gotta go now. I'll be back later.
Good luck! ;D

Anomie
Member #9,403
January 2008
avatar

Alright, I have to go for the night (1:22 here, and I have to be up in the morning), but I'll try and work through this, or write my own. I generally have a big problem working out how other peoples' code works. (that'd be why I didn't look into other engines when I started working on this)

Thanks for the help.

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

I'll try to make things clearer...
Note that in the following, every time I say "polygon", I mean a convex polygon, a line, or a point. The code I present here is simpler than what I have in my previous post, because this code only tells you whether there is an overlap, but gives no information about how to resolve it.
If you can figure this out, I'll write another short tutorial explaining how to get a the minimal translation vector that would separate the two objects after the overlap.

Let's suppose that we're dealing with overlaps in one dimension.
We have a single axis, and the "objects" are represented by intervals on this axis.
Each interval has a minimum and a maximum value.

intervalsae3.png

Checking whether two intervals overlap is very straight-forward:
Two intervals overlap, unless one of the interval's minimum is bigger than the other's maximum.

int intervals_intersect(INTERVAL int0, INTERVAL int1)
{
 if(int0.min > int1.max || int1.min > int0.max)
  return 0;
 return 1;
}

Now, let's move on to two dimensions.
It's an obvious fact that if you can draw a line between two convex polygons, such that each polygon would end up on a different side of the line,
the line separates the two polygons and they can't possibly be overlapping.
If no such line exists, then the polygons are overlapping.

http://img520.imageshack.us/img520/9764/slgj7.png

So we can state our problem this way: Check every potential separating line: if the line checked separates the polygons, terminate the
test and declare the polygons as non-overlapping. If none of the potential separating lines actually separate the polygons, they overlap.
Obviously, there's an infinite amount of lines we could test, so the trick is chosing a finite set that would give us conclusive results.
We'll get back to that later.
So how do we actually check if a line separates two convex polygons?
There are plenty of ways to do that, but the one I will present will prove to be very useful later on:
We find the normal of the line we're testing, we normalize it and project both polygons on it.
To project an polygon on the normal, we take the dot product of that normal and every vertex of the polygon.
The result of the dot product would be a scalar value, and if we imagine the normal to be a 1D axis, then this value would represent each point's
location on this axis.
For each polygon, we find the minimum and maximum of the dot product results.
The extrema give us the polygon's interval on the axis.

polyintmt5.png

1INTERVAL poly_interval_on_axis(VECTOR poly[], int n, VECTOR axis)
2{
3 int i;
4 double temp;
5 INTERVAL interval;
6 
7 interval.min = interval.max = VECTOR_DOT_PRODUCT(axis, poly[0]);
8 
9 for(i = 1; i < n; i++)
10 {
11 temp = VECTOR_DOT_PRODUCT(axis, poly<i>);
12 
13 if(temp < interval.min) { interval.min = temp; }
14 if(temp > interval.max) { interval.max = temp; }
15 }
16 
17 return interval;
18}

.
If the two intervals of the projected polygons don't overlap, the line separates the polygons.

{"name":"seplinerj5.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/4\/84cdd11457f968e7f7146198b6e7ecfb.png","w":245,"h":229,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/4\/84cdd11457f968e7f7146198b6e7ecfb"}seplinerj5.png

It can be proven that while there's an infinite number of such lines we could test, we only need to test a handful:
We only need to take each side of each polygon as a potential separating line.
If we find one that separates the polygons, we terminate the test and declare the polygons as non-overlapping.
If none of the them separate the polygons, they overlap.

1//'a', 'b' - polygon vertices. 'an', 'bn' - polygon normals.
2// 'n0' - number of vertices of the 1st polygon, 'n1' - number of vertices of the 2nd.
3int poly_intersection_test(VECTOR a[], VECTOR b[], VECTOR an[], VECTOR bn[], int n0, int n1)
4{
5 VECTOR axis;
6 int i;
7 
8 for(i = 0; i < n0; i++)
9 if(!intervals_intersect(poly_interval_on_axis(a, n0, an<i>), poly_interval_on_axis(b, n1, an<i>)))
10 return 0;
11 
12 for(i = 0; i < n1; i++)
13 if(!intervals_intersect(poly_interval_on_axis(a, n0, bn<i>), poly_interval_on_axis(b, n1, bn<i>)))
14 return 0;
15 
16 return 1;
17}

OnlineCop
Member #7,919
October 2006
avatar

Wow, Stas B., I don't think even Wikipedia was able to explain it to me that clearly. Bookmarked! (And good use of simple-but-efficient graphics!)

Anomie
Member #9,403
January 2008
avatar

Damn. You didn't have to go through that much trouble, though I think you've just written a good SAT resource.

And did a good job, too! Yeah, all of those snippets make perfect sense now. Hang on, I'm going to go look at the rest...

I think the only stuff that I don't get at this point is involved with the projection, but I never got around to looking into how that stuff works.

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

I knew I should have written something about projection.
It's quite simple:
projectionmathph3.png

The red point is the point we are projecting.
The bold black line is the vector B that we project the point onto, and the black point is its origin.
The green point is the projected point.
We form a right triangle between the three points.
What we're searching for is the distance between the black and green point.
Basic trigonometry tells us that it's |A|*cos(a), but we don't really know 'a'.
Luckily for us, |A|*cos(a) is exactly what A dot B is defined to be.
So how does that help? Another definition of A dot B would be Ax * Bx + Ay * By.
So the projection of point A on vector B would be Ax * Bx + Ay * By.

P.S.:
Thanks for the good comments.
People ask about collision detection often, so I figured I should write something about it. The first time I implemented SAT was after reading tons of info from many different web-pages, and even then I was not entirely sure what I was doing. I figured out how exactly it works since then, so I did my best to make a clear, short tutorial, so people won't have to go through much trouble.
Perhaps I should move this to somewhere where it can be more easily found?
Any suggestions?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Anomie
Member #9,403
January 2008
avatar

Oh, sorry...I should have been more clear. By 'projection', I meant the process of projecting the objects out of collision. (But that bit you just posted is actually exactly what I'm doing in my Geometry class right now...kinda funny...)

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

I have a feeling this is going to be a lot less clear...

To resolve an overlap between two polygons, what we need to do is to turn one of the potential separating lines we discussed earlier into a real separating line. To do so, we need to make sure that the intervals of the polygons on the normal of that line stop overlapping.
This can be done by translating one of the polygons a certain amount in the direction (or the opposite direction) of the normal.
We compute a translation vector: Its direction is the direction of the normal (or opposite to it), its length is the amount of interval overlap (the area the intervals share).

{"name":"resoverip8.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/a\/3a352044bcb17bfa86fd0ea827deaa78.png","w":553,"h":208,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/a\/3a352044bcb17bfa86fd0ea827deaa78"}resoverip8.png

Note that in the picture, the blue rectangle is penetrating the red one from the right, so we would push it in the direction of the normal, to the right.
If it was penetrating from the left, we could still push it all the way to the right, but the reasonable thing to do would be to push it in the opposite direction, to the left.
First thing, we need to update our 'intervals_intersect' function to return the amount of overlap:

int intervals_intersect(INTERVAL int0, INTERVAL int1, double *depth)
{
 double d0, d1;

 if(int0.min > int1.max || int1.min > int0.max)
  return 0;

 d0 = int0.max - int1.min;
 d1 = int1.max - int0.min;

 *depth = (d0 < d1) ? -d0 : d1;
 return 1;
}

Note that 'depth' could be either positive or be negative, with plus meaning "in the direction of the normal" and minus meaning "in the opposite direction".
We could chose any side of the any of the polygons to separate the two, but for each line, the amount of translation needed to separate the objects would be different. The reasonable choice would be the line with the shortest translation vector, or in other words, with the smallest amount of interval overlap.
(Note that since we're doing a static test (i.e., not taking velocities into account), sometimes it might not be the most correct solution,
but it should be satisfactory in most cases.)
Here, for example, we would translate the polygon horizontally, since the amount of overlap is smaller:
{"name":"resover2cb8.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/b\/3b4dc9dfbf4b045ca087b8f599477056.png","w":279,"h":205,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/b\/3b4dc9dfbf4b045ca087b8f599477056"}resover2cb8.png

So here's an updated version of the 'poly_intersection_test', which would not only tell us if the objects overlap, but also how much and in
what direction to push them so they stop overlapping.
This code finds the normal with the smallest interval overlap and the actual smallest amount of overlap, then creates a minimal translation vector by scaling the (normalized) normal by the overlap amount.

1int poly_intersection_test(VECTOR a[], VECTOR b[], VECTOR an[], VECTOR bn[], int n0, int n1, VECTOR *mtd, VECTOR *n)
2{
3 VECTOR axis;
4 double depth, min_depth = 10000000.0;
5 int i, k;
6 
7 for(i = 0; i < n0; i++)
8 {
9 if(!intervals_intersect(poly_interval_on_axis(a, n0, an<i>), poly_interval_on_axis(b, n1, an<i>), &depth))
10 return 0;
11 
12 if(fabs(depth) < fabs(min_depth))
13 {
14 min_depth = depth;
15 k = i;
16 }
17 }
18 
19 for(i = 0; i < n1; i++)
20 {
21 if(!intervals_intersect(poly_interval_on_axis(a, n0, bn<i>), poly_interval_on_axis(b, n1, bn<i>), &depth))
22 return 0;
23 
24 if(fabs(depth) < fabs(min_depth))
25 {
26 min_depth = depth;
27 k = n0 + i;
28 }
29 }
30 
31 if(k < n0)
32 {
33 *mtd = USCALE_VECTOR(an[k], min_depth);
34 *n = an[k];
35 }
36 
37 else
38 {
39 *mtd = USCALE_VECTOR(bn[k - n0], min_depth);
40 *n = bn[k - n0];
41 }
42 
43 return 1;
44}

Note that you can apply the resulting translation vector is several ways.
You could make one polygon immovable (world geometry, for example) and apply all the translation to one of the polygons, or you could
push each polygon in an opposite direction with half of the translation distance.
You could use the mass ratio to figure how much translation to apply to which polygon.

Anomie
Member #9,403
January 2008
avatar

Awesome! That makes things much clearer. I'm probably going to rewrite this stuff myself (just because I'm awkward), but I'm thinking the background of the demo (if I ever release this thing) is going to be filled with "80% of this system thanks to: Stas B. and James Lohr" in huge glowing letters...or something...

Thanks again!

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

You're welcome. ;D

P.S.:
I've just finished coding the dynamic version of the algorithm.
Works like a charm for lines and polygons at any velocity and just a bit more complicated than the static test.
I'm a bit too lazy to explain how it works right now, but here's the code:

1VECTOR poly_interval_on_axis(VECTOR poly[], int n, VECTOR axis)
2{
3 int i;
4 float temp;
5 VECTOR interval;
6 
7 interval.x = interval.y = VECTOR_DOT_PRODUCT(axis, poly[0]);
8 
9 for(i = 1; i < n; i++)
10 {
11 temp = VECTOR_DOT_PRODUCT(axis, poly<i>);
12 
13 if(temp < interval.x) { interval.x = temp; }
14 if(temp > interval.y) { interval.y = temp; }
15 }
16 
17 return interval;
18}
19 
20int intervals_intersect(VECTOR int0, VECTOR int1, float pv, float *depth)
21{
22 float d0, d1;
23 
24 if(int0.x > int1.y)
25 if(int0.x + pv > int1.y)
26 return 0;
27 else
28 {
29 *depth = (int0.x - int1.y) / fabs(pv);
30 return 2;
31 }
32 
33 if(int1.x > int0.y)
34 if(int0.y + pv < int1.x)
35 return 0;
36 else
37 {
38 *depth = (int1.x - int0.y) / fabs(pv);
39 return 2;
40 }
41 
42 d0 = int0.y - int1.x;
43 d1 = int1.y - int0.x;
44 
45 *depth = (d0 < d1) ? -d0 : d1;
46 return 1;
47}
48 
49int poly_intersection_test(VECTOR a[], VECTOR b[], VECTOR an[], VECTOR bn[], int n0, int n1, VECTOR rel_vel, VECTOR *mtd, VECTOR *n)
50{
51 float depth, min_depth = 10000000.0, pv, scale_vel = -10.0;
52 int i, k, flag, future_overlap = 0;
53 
54 for(i = 0; i < n0; i++)
55 {
56 pv = VECTOR_DOT_PRODUCT(an<i>, rel_vel);
57 flag = intervals_intersect(poly_interval_on_axis(a, n0, an<i>), poly_interval_on_axis(b, n1, an<i>), pv, &depth);
58 
59 if(!flag) return 0;
60 if(flag == 1 && fabs(depth) < fabs(min_depth))
61 {
62 min_depth = depth;
63 k = i;
64 }
65 
66 if(flag == 2)
67 {
68 future_overlap = 2;
69 if(depth > scale_vel) scale_vel = depth;
70 }
71 }
72 
73 for(i = 0; i < n1; i++)
74 {
75 pv = VECTOR_DOT_PRODUCT(bn<i>, rel_vel);
76 flag = intervals_intersect(poly_interval_on_axis(a, n0, bn<i>), poly_interval_on_axis(b, n1, bn<i>), pv, &depth);
77 
78 if(!flag) return 0;
79 if(flag == 1 && fabs(depth) < fabs(min_depth))
80 {
81 min_depth = depth;
82 k = n0 + i;
83 }
84 
85 if(flag == 2)
86 {
87 future_overlap = 2;
88 if(depth > scale_vel) scale_vel = depth;
89 }
90 }
91 
92 VECTOR v_axis = normalized_vector(VECTOR_NORMAL(rel_vel));
93 pv = VECTOR_DOT_PRODUCT(v_axis, rel_vel);
94 flag = intervals_intersect(poly_interval_on_axis(a, n0, v_axis), poly_interval_on_axis(b, n1, v_axis), pv, &depth);
95 if(flag == 0) return 0;
96 
97 if(future_overlap == 2)
98 {
99 *mtd = vector(scale_vel, scale_vel);
100 return 2;
101 }
102 
103 if(k < n0)
104 {
105 *mtd = USCALE_VECTOR(an[k], min_depth);
106 *n = an[k];
107 }
108 
109 else
110 {
111 *mtd = USCALE_VECTOR(bn[k - n0], min_depth);
112 *n = bn[k - n0];
113 }
114 
115 return 1;
116}

GullRaDriel
Member #3,861
September 2003
avatar

Usefull code, indeed. Thanks Stas B !

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Stas B.
Member #9,615
March 2008

Sorry, Anomie, but it turns out to be totally not worth it. :-/
Working out the contact points is a real pain in the butt and I'm pretty sure it's gonna be as slow as your original algorithm eventually.
Also, dynamic SAT wouldn't work right for you, because it assumes that all points of a given object are moving at the same velocity, but in your case, a line segment might rotate, so each point would move with a different velocity. (A work-around might be to just chose the greater velocity for the test, but I'm not sure how it would turn out.)

[EDIT]

Now that I think of it, your algorithm would suffer from the "points with different velocities" problem too.
And if you do only lines vs. lines, figuring out the contact points would be a matter of another line intersection test after the collision has been resolved...
Damn, there's just no good way to deal with this problem!
No wonder even the most complex modern computer games use spheres and boxes for collisions. ::)

Anomie
Member #9,403
January 2008
avatar

Quote:

it's gonna be as slow as your original algorithm eventually.

Meh...that doesn't really bother me too much.

Quote:

Also, dynamic SAT wouldn't work right for you, because it assumes that all points of a given object are moving at the same velocity, but in your case, a line segment might rotate, so each point would move with a different velocity.

But the way I was thinking of doing it, I would only check points (totally separate from eachother and anything else) against lines (totally separate from eachother and everything else). The only 'objects' I would have would be singles lines, and single points. Would that still be a problem? (or would it work at all? (or would it really just fix everything if I used polygons/circles for my points/lines? (and could I model my lines as having sub-pixel width?)))

In any case, you've written a good new resource here! Not a total waste of time, even if it can't be used in my little thingy.

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Tobias Dammers
Member #2,604
August 2002
avatar

You guys draw nice colorful pictures. I love this thread.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Stas B.
Member #9,615
March 2008

Points and lines bring us back to the problems we were trying to avoid.
There's really no point in using SAT if that's your plan, because you're essentially just using it for the line intersection tests you could do with 5th grade math.
It brings us back to these problems:
{"name":"05cb8cbdb1af89c2578439bf1773e7c8.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/a\/9a2cd2c8bef78347bfe9661e68280bbb.png","w":265,"h":368,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/a\/9a2cd2c8bef78347bfe9661e68280bbb"}05cb8cbdb1af89c2578439bf1773e7c8.png
Which you wanted to resolve by doubling the number of needed tests and using relative velocities... But you have to use one relative velocity while each point could be moving with a different one - the same problem with SAT.
The problem with your algorithm is that while it's perfectly fine for separate points, it can't handle well an object as a whole. That's why I suggested SAT: It's great at handling whole objects... But I almost forgot that the objects have to be convex for it to work. So I suggested breaking the objects into lines (each side of each polygon would be a line, so only lines vs. lines, no points), but that introduces new problems... Well, in fact, it introduces only one new problem because the "two different velicities" problem is present in both cases. The problem is finding the contact points. (Which could be done, but I think that by the time you're done with it, it would be a mess.)

Anomie
Member #9,403
January 2008
avatar

Damn... It sounds like the dynamic SAT won't work if things can rotate, and even if I used full polygons, the standard static SAT can't be trusted unless I make my lines out of really thick rectangles... I know people have done this before me! Argh! I need to think more.

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

SAT does perfectly well for objects that rotate, unless they rotate really really fast. But if they rotate that fast, you can treat them like circles. So that's really not a concern.
And the thing is, people haven't done it before you... they just stick to convex shapes. I've never seen a reasonable solution for collision detection between concave shapes.

[EDIT]

Okay, this might sound like a crazy idea, but... well... you COULD break your objects into lots of lots of little circles and test those for collision.
Since you're working in 2D, AND you could use a bounding circle hierarchy, it won't be too slow. You can use fast distance approximation for the tests.
I'm pretty sure more complex operations are done in real-time per-pixel nowadays than you'll have to do for each circle.
It's a simple solution and it would mimic the way the real world works. ;D

Anomie
Member #9,403
January 2008
avatar

Quote:

SAT does pefectly well for objects that rotate ...

The 'two different velocities' thing? Unless it's a perfect square, I guess...but I know that people have made systems where everything is made of point-masses/springs. I guess the solution may really be to find a way to separate everything into convex polygons dynamically...but gawd. It seems so ridiculous that the whole thing was made so much more complicated by gravity. It looks like 95% of the code in this system is going to be for the collision stuff.

[edit] As in...having even my lines made of tiny circles? Huh... I guess, if I really wanted to, I could move things at a fifth their normal speed, and do five times as many ticks per second, to try and avoid missing collisions due to high speeds... Could that really work?

[edit2] Wait, how would that be different from a simple distance-to-line check?

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

;DYou don't have the "different velocities" problem (nor any other problem we've discussed) if you use convex polygons and separate rotational velocity from translational velocity. I have a rigid body dynamics demo that works that way, and it handles rotations very well, thank you. (And probably looks more realistic than a mass\spring system.) ;D
But the hell with that.
You don't need to break your objects into convex polygons, you can break them into circles.
If would be really simple to both break them and check them.
The more I think of it, the better this solution seems.

[EDIT]

You won't have missed collision problems if you FILL the areas of your objects with circles.
It isn't really THAT crazy if you use a boudning circle hierarchy. ;D

[EDIT 2]

You'll need to think of a smart way to fill in your circles, so you can cover the whole area of the object with as small number of circles as possible.

[EDIT 3]
In fact, you can make only your lines out of circles but do DYNAMIC circle/circle tests, so no collisions would be missed.

Anomie
Member #9,403
January 2008
avatar

Oooooooh, I see! That makes more sense. So then... It still seems like I'd have to identify the shapes with enough accuracy to separate them into polygons...the hard part would be finding the center of a connected shape, with respect to the possibility of something like a box and a pole, attached by a rope of springs...which would each need to be registered separately for the circles, right?

[edit] I must just be real slow with my posting. :P If I do make my lines out of circles and test those, how's that different from the distance-to-line check?

______________
I am the Lorax. I speak for the trees. I speak for the trees for the trees have no tongues.

Stas B.
Member #9,615
March 2008

The difference is that you won't encounter any of those old problems that way.
Come on, just take a sheet of paper and do some drawing.
My computer got... ummm.... confiscated, so I can't really post much, but I'll try to post something if I figure out a good solution.

 1   2 


Go to: