Division on Zero

Discuss any Chipmunk bugs here.
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Division on Zero

Post by ShiftZ »

One more... no, not div by zero. Got invalid floating point operation on cpSpaceHash.c: 230 while trying to add a new shape in scene:

static inline int
floor_int(cpFloat f)
{
int i = (int)f;
...

it caused by uninitialized values of shape->bb.
Initialization has been commented for some reason cpShape.c:65
// cpShapeCacheBB(shape);

shape may have huge bb size and filll whole hash space, also may lead to very long loop casescpSpaceHash:245.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Division on Zero

Post by slembcke »

This should be fixed in trunk as of a couple weeks ago. I had intended to move it so that the bounding box wouldn't be calculated until the shape was actually added to the space. (This was causing some other bug) It seems I missed a couple of cases though.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Division on Zero

Post by ShiftZ »

Anyone know how to trap floating point exception on iPhone.
I had no success. All i can do is just check if floating point exception flag is raised, but it's usless without exact raising location.
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Division on Zero

Post by ShiftZ »

slembcke
Hi, again constanly catching floating point exception.

cpPolyShape.c:
cpPolyShapeSegmentQuery(cpPolyShape *poly, cpVect a, cpVect b, cpSegmentQueryInfo *info)

Code: Select all

cpFloat an = cpvdot(a, n);
if(axes[i].d > an) continue;
		
cpFloat bn = cpvdot(b, n);
cpFloat t = (axes[i].d - an)/(bn - an);
If vector a and b enough distant from center (0, 0) and pretty close to each other, then quite likely bn and an would be equal due to lack of float precision. For example :
a.x -132.42502 float
a.y -91.492790 float

b.x -134.37552 float
b.y -90.621086 float

n.x 0.40801811 float
n.y 0.91297394 float

gives equal bn an and division by zero as result. Note that a and b are pretty common values, it's not an exotic case. More distant values gives div by zero more often. I think there should be a way to avoid such inconsistence.
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Division on Zero

Post by ShiftZ »

slembcke
Well, anyway, it is missing extra condition check

Code: Select all

 if (an == bn) continue; 
in case if ab segment is parallel to polygon edge.


The only thing that i cannot understand is that:

Code: Select all

if(axes[i].d > an) continue;
What does it mean? Why it is working?
Last edited by ShiftZ on Fri Sep 23, 2011 9:59 am, edited 1 time in total.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Division on Zero

Post by slembcke »

Hmm. That's sort of nasty. I'll have to rearrange some of those ops to use the available precision better. It's hitting that surface very nearly parallel to it's surface causing the dot products to be nearly equal even when the line segment size is not particularly small.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Division on Zero

Post by slembcke »

Code: Select all

if(axes[i].d > an) continue;
That checks if the starting point of the segment query is already behind that particular axis. Queries aren't checked against the interior of shapes, so it needs to reject those cases.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Division on Zero

Post by ShiftZ »

slembcke wrote:Hmm. That's sort of nasty. I'll have to rearrange some of those ops to use the available precision better.
You can localize calculation of t, but actually there is no need to do that since very close an and bn unlikly hit the poly edge. All you need to fix it is just to add extra condition check:

Code: Select all

cpFloat an = cpvdot(a, n);
if(axes[i].d > an) continue;
      
cpFloat bn = cpvdot(b, n);
if (an == bn) continue; // Parallel surfaces or very close to parallel
cpFloat t = (axes[i].d - an)/(bn - an);
However this wont fix a rare case of distant segment close to parallel, but still crossing the edge. It wont hit and this will be a bug. To fix it you'll have to calculate t relative one of the poly vertex. Something link:
float an = (a - v) dot n;
float bn = (b - v) dot n;
float t = an / (bn - an);
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Division on Zero

Post by ShiftZ »

Hey, another division by zero here

Code: Select all

cpBB.h:
static inline cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b)
{
	cpFloat idx = 1.0f/(b.x - a.x);
	cpFloat tx1 = (bb.l == a.x ? -INFINITY : (bb.l - a.x)*idx);
	cpFloat tx2 = (bb.r == a.x ?  INFINITY : (bb.r - a.x)*idx);
	cpFloat txmin = cpfmin(tx1, tx2);
	cpFloat txmax = cpfmax(tx1, tx2);
	
	cpFloat idy = 1.0f/(b.y - a.y);
	cpFloat ty1 = (bb.b == a.y ? -INFINITY : (bb.b - a.y)*idy);
	cpFloat ty2 = (bb.t == a.y ?  INFINITY : (bb.t - a.y)*idy);
	cpFloat tymin = cpfmin(ty1, ty2);
	cpFloat tymax = cpfmax(ty1, ty2);
1.0f/(b.x - a.x) and 1.0f/(b.y - a.y);
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Division on Zero

Post by slembcke »

Yes, those were intended to produce infinity for horizontal or vertical lines.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest