Archive for the 'Physics' Category

Funniest way to fix a physics bug

Monday, June 27th, 2011

I was playing Red Faction Armageddon this week-end when my Xbox suddenly froze. Apparently I’m not the only one having this issue, they released that game with a big “physics bug” in it:

http://www.redfaction.com/forums/topic/14022

(Havok, tsss, tsss!)

Now the funny thing is the workaround that players quickly found: if you destroy everything in the area before pulling the switch (a 100% crash repro otherwise), the bug vanishes :) I guess I’ll have to try that.

Still very disappointing. So far RF Guerilla was 10 times better.

SAP code bugfix

Monday, March 14th, 2011

This is embarrassing, but there was a bug in the previously posted SAP code. Fetch the new version here:

http://www.codercorner.com/Code/SweepAndPrune3.rar

Thanks to Olli-Pekka Räsänen for reporting it!

Faster convex-convex SAT: internal objects

Monday, January 24th, 2011

I noticed that I had a fairly low amount of posts in the “physics” category, for somebody working in physics & collision detection all day long. So let me try to increase the ratio a bit. Last time we talked about partial hulls, today I’ll present another optimization for the same problem.
The penetration depth between two convex polytopes can easily be computed using separating-axis tests. But the large number of edge-edge tests often makes this process very slow, and other algorithms such as EPA or Xenocollide are thus often chosen over SAT to compute the MTD between two convexes. There are however a large number of tricks to optimize the SAT version. One of the most efficient ones is to use simple “internal objects”, i.e. simple objects such as a sphere or a box embedded in the convex.
Recall that for each candidate axis we do something like:
bool testSepAxis(const btVector3& axis, const MyConvex& hull0, const MyConvex& hull1, float& dmin, Vector3& mtd)
{
// Project hull 0 on candidate axis
float Min0,Max0;
hull0.Project(axis, Min0, Max0);
// Project hull 1 on candidate axis
float Min1,Max1;
hull1.Project(axis, Min1, Max1);
// If the projected intervals don’t overlap, the candidate axis is a separating axis.
// In that case the hulls don’t overlap, we can early exit and return non penetration.
if(Max0<Min1 || Max1<Min0)
return false;
// Else compute penetration depth (PD) = how much the intervals overlap
const float d0 = Max0 - Min1;
const float d1 = Max1 - Min0;
const float depth = d0<d1 ? d0:d1;
// Then keep track of minimal PD. The axis for which the PD is minimal is the MTD.
if(d<dmin)
{
dmin = d;
mtd = axis;
}
return true;
}
So we’re looking for the minimal overlap, and the MTD is the axis for which the overlap is minimal. The idea, then, is to first project the simpler, internal objects on the candidate axis, and use the overlap results to skip the real hull projections if we can.
Say our internal objects are spheres (it could also be boxes, but for the sake of the argument let’s use spheres). Let hullOverlap(V) be the overlap value for the hulls on a given axis V, and sphereOverlap(V) be the one for the spheres on the same axis. Since spheres are embedded in the hulls, it should be clear that we always have:
hullOverlap(V) >= sphereOverlap(V)  (1)   (see Figure 1)
Now let minHullOverlap be our current best result, i.e. our current minimal penetration depth computed from real hull projections (not sphere projections). It should be obvious that thanks to (1) we have:
sphereOverlap(V) > minHullOverlap  => hullOverlap(V) > minHullOverlap   (2)
In other words, if sphereOverlap(V) is already bigger than our current best result, hullOverlap(V) will be bigger as well, and thus there is no need to compute it.

Internal objects

Figure 1
This is interesting since, of course, projecting a sphere is a lot faster than projecting a convex hull. Projecting a sphere is one dot product, projecting a hull is one dot product per vertex (plus, we don’t need to even access the vertex memory).
As Figure 1 shows, the embedded spheres don’t need to actually touch for this test to be useful - only the spheres’ projections on the candidate axis. In practice, this happens very often, and that single optimization sometimes culls away 90% of the actual hull projections. You can try out this demo for a proof-of-concept.
It is also a good idea to test the MTD from the previous frame first, to initialize minHullOverlap to a small value right from the start - discarding candidate axes as early as possible.
Finally a note about the internal shapes one should choose. A sphere might not be a great fit for long thin rods, in which case an embedded box might be better. But it might be easier to just use both, and at runtime choose whatever internal shape gives the best results. This is what I do in the above demo.

Lighthouse demo

Thursday, September 23rd, 2010

The coolest demo to ever come out of the Zürich office is finally public:

http://physxinfo.com/news/4331/physics-demos-from-nvidia-gtc-keynote/

I mentioned that one to some people before, now you can have a look :)

New sweep-and-prune paper

Monday, September 20th, 2010

Here’s an interesting new paper:

http://graphics.ewha.ac.kr/gSaP/

http://graphics.ewha.ac.kr/gSaP/gSaP.pdf

I’m not sure where they got that though:

“Moreover, [Terdiman 2007] hypothesized that parallelizing the hybrid SaP and subdivision may perform poorly”.

Did I? I just briefly explained how to do it but I don’t think I ever wrote “it may perform poorly”. Or show me where, because I don’t remember. In fact, I didn’t investigate this path well enough to know. But this is interesting and motivating, maybe I will now :)

“This algorithm may be considered as a parallel version of that proposed by [Terdiman 2007]”.

Hmm, but I already explained the parallel version in that paper, didn’t I? So it’s basically a parallel implementation of an MSAP, which I already detailled in 2007 (and it wasn’t even new at the time). No? Well ok, for GPU.

I should note that I’ve made the “ArraySAP” in that benchmark a bit faster than it used to be (especially insertions can now be 2X faster), but overall it doesn’t change their good results.

Oh, and I’ve used PCA to compute the best axis years ago already, in Z-Collide :)

SAP in 1999, SAP in 2010… I just can’t escape :(

Your raycast-vs-sphere code is broken

Monday, August 17th, 2009

Check your codebase if you don’t believe me. I posted this months ago on GDA but never found the time to make a proper note. And you know what? I still don’t have the time. Check the GDA archives for more information.

In short: the code solving the quadratic equation suffers from limited FPU accuracy and returns “no intersection” while there definitely is one. “Best” fix is to move the ray origin closer to the target sphere. See this small repro case for details.

It’s not a theoretical problem only, it happened in Konoko Payne when sniping a far away enemy with a Mercury Bow.

So, there. Off my TODO list, stupid item!

NVIDIA PhysX 2.8.1

Thursday, May 15th, 2008

So they released a new PhysX version, and this time the character controller (CCT) source code is included. Partially. For various reasons they decided not to release the source code for the actual sweep tests (box-vs-box, capsule-vs-capsule, capsule-vs-mesh, etc). So the SDK exposes them as utility functions and the CCT code just accesses them through the NxUtility interface. However all the code for the CCT logic has been released.

I originally wrote the CCT as part of ICE, for Konoko Payne. It was many years ago, before I joined Novodex. Then I integrated it to the Novodex SDK, it got rewritten, refactored to use the NX math classes, etc. Then for some reasons it got moved outside of the SDK, in its own NxCharacter DLL. Then filtering callbacks were removed because of the Ageia hardware (the original plan was to move the CCT to HW, so callbacks were forbidden.) Then fixes sent to us by various customers got integrated. Then I rewrote it for “large worlds”, using doubles for positions. Then this feature was dropped, a decision I’m still bitter about. Then the code got modified by various people over the years. Then the code was rewritten again to remove the sweep tests, which got exposed as NxUtility functions instead. And then the final code was released, probably because they got tired of modifying the CCT for each individual customer (they always want something a little bit different).

Looking at it again today, I have mixed feelings. One one hand it still does its job more or less correctly. On the other hand, it’s a bit in a sad state by now:

  • It’s a bit bloated, with some useless code that could be dropped.
  • It has O(n^2) parts to deal with character-character interactions and it misses an incremental SAP to support “sleeping characters” (to avoid testing all of them each frame). This is because the SDK didn’t expose its SAP interface directly to users.
  • It doesn’t support large worlds even though the code structure is ready for it (relocating everything around the player’s position instead of working in world-space, etc).
  • It’s probably not as fast as it could be, since the CCT was never a big priority for Ageia (sometimes I had the feeling nobody cared about it. It wasn’t HW accelerated so it wasn’t important. Sigh.)

The current CCT used in KP is basically the same. But without the problems. That’s because a single person touched the code, and no political reason ever motivated a code change. It’s a bit sad that the code I produce alone in my free time (Opcode, Flexporter, etc) often ends up in a better shape and faster than the code produced within a company, where N people with different mindsets and sometimes conflicting views are allowed to change it. It worked great within Novodex because we were only 2 people, “owning” clearly defined parts of the code: Adam was in charge of the solver & joints, I was in charge of the collision detection. We never stepped on each-other’s steps, as far as I can remember. Within Ageia… let’s just say things were different.

PPU R.I.P.

Monday, March 10th, 2008

I guess it’s not a big surprise but now it’s official

Faster convex-convex SAT : partial hulls

Friday, February 22nd, 2008

Here’s a question I received in my mailbox a while back:

I am looking into the SAT code for small convex meshes here at the moment and it doesn’t seem very effcient. Can you share some ideas how to reduce the number of tests. Especially the number of edge/edge tests seems to grow huge.

There would be a lot to say about this. But one way is to replace colliding convexes with simpler versions (I call them “partial hulls”). Take a look at the following picture:

Partial hulls

The two overlapping convexes have a red part and a green part. The key observation is that the penetration depth and the penetration direction (the yellow line) do not depend on the green parts - which can be safely ignored. The penetration would be the same if the convexes would be “closed” by the blue segments.

So the trick is simple in theory: ignore the green parts, and compute the penetration distance using the “partial hulls” enclosed between the red and blue segments. It has two direct benefits:

  • the number of edge/edge tests is greatly reduced (that’s clearly the main advantage).
  • the green vertices can also be ignored in the projection code

How to implement this efficiently is another (long) story, but here is a small proof-of-concept test that already runs orders of magnitude faster than the brute-force Separating Axis Theorem.

Free Havok

Friday, February 22nd, 2008

Wow!

shopfr.org cialis