PDA

View Full Version : 3d Collision Detection



Jerryscript
February 29th, 2004, 02:03 AM
I'm having a bit of trouble with psuedo 3d collisions using spheres. I'm using _xscale and _yscale to emulate the z-axis (no horizon point), and am having trouble determining the distance between the objects on the z-axis based upon their relative scales.

I'm not concerned at this moment with creating new vectors based upon hit angles, just getting the z-index collision detection working.

(I also need to tweak the code to prevent trapping, so much todo)

Here's the code, the issue is how do I determine the correct value for the z-axis in the hittest?
note-this only works when I publish in flash6 when using mx2004, the collision detection doesn't work at all when published for flash7?!?

MovieClip.prototype.moveRandom=function(){
// create a random vector
this.vx=0;
this.vy=0;
this.va=0;
while(this.vx==0){this.vx=Math.round((Math.random( )*1-1)*(Math.random()*10));}
while(this.vy==0){this.vy=Math.round((Math.random( )*1-1)*(Math.random()*10));}
while(this.va==0){this.va=Math.round((Math.random( )*1-1)*(Math.random()*10));}
this.onEnterFrame=function(){
// move the spheres along their vector
this._x+=this.vx;
this._y+=this.vy;
this._xscale+=this.va;
this._yscale+=this.va;
this.swapDepths(this._yscale*1000+this.id*10);
if(this._x>Stage.width || this._x<0){
this.vx*=-1;
}
if(this._y>Stage.height || this._y<0){
this.vy*=-1;
}
if(this._xscale>=100 || this._xscale<=0){
this.va*=-1;
}
// 3d collision detection
thisone=this;
for(p=1;p<_root.particlecount;p++){
if(_root[p]!=thisone){

// THIS IS THE LINE WITH THE PROBLEM
if(thisone.hittest(_root[p]) && Math.abs(thisone._xscale-_root[p]._xscale)<5){
_root[p].vx*=-1;
_root[p].vy*=-1;
_root[p].va*=-1;
}
}
}
updateAfterEvent();
};// end enterframe
};// end move random prototype

// create the spheres
particlecount=15;
for(p=1;p<=particlecount;p++){
_root.createEmptyMovieClip(p,p);
with(_root[p]){
id=p;
a=b=20;
colors =[ 0xffffff,Math.round(Math.random()*0xffffff) ];
alphas =[ 100,100 ];
ratios =[ 0,255 ];
matrix ={matrixType:'box',x:-a/1.5,y:-b*1.5,w:a*2,h:b*2,r:(90/180)*Math.PI };
lineStyle(1,0x0000ff,0);
beginGradientFill('radial',colors,alphas,ratios,ma trix );
j=a*0.70711;n=b*0.70711;
i=j-(b-n)*a/b;m=n-(a-j)*b/a;
moveTo(a,0);
curveTo(a,-m,j,-n);
curveTo(i,-b,0,-b);
curveTo(-i,-b,-j,-n);
curveTo(-a,-m,-a,0);
curveTo(-a,m,-j,n);
curveTo(-i,b,0,b);
curveTo(i,b,j,n);
curveTo(a,m,a,0);
endFill();
_x=Math.ceil(Math.random()*(500-_xscale)+_xscale/2);
_y=Math.ceil(Math.random()*(250-_yscale)+_yscale/2);
_xscale=_yscale=Math.ceil(Math.random()*100);
}
_root[p].moveRandom();
}

Thanks for any help offered!

davidchang
February 29th, 2004, 03:32 AM
well... i dont recommend the hitTest and suggest u use geometry, if u have the (3D) centre of two spheres then the distance between the centre of the two spheres is: Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + Math.pow(z1 - z2, 2)); with the centre of the sphere1 and sphere2 being (x1, y1, z1) and (x2, y2, z3) respectively.

I didnt bother reading the rest of this scale business u got going on.

i hope this helps...

Jerryscript
February 29th, 2004, 04:28 AM
Thanks, unfortunately, using geometry slows things down when you get beyond 10-15 objects depending upon the processor (unless someone knows a trick to calculate the distance faster?). That's why I was using the hittest shortcut. It's even worse when I factor in a horizon for perspective. The flash player's AS engine just isn't built for real 3d.

It appears as if using the radius of the sphere (20 instead of 5) in the line I asked about is ok, so long as I stay away from perspective/horizon. I think it is the trapping bug I need to fix that was making me question the use of the radius.

Hmmm, I wonder if once I switch to using vectors for the direction change after collisions, would it be faster to calculate the vectors for each object upon a collision (with the wall or another object) and plot intersection points between them? That way the collisions would be precalculated after each collision event instead of determined dynamically through current coordinates... anyone ever seen this approach?

pom
February 29th, 2004, 10:47 AM
You don't have the choice. HitTest is a 'flat' collision detection. If two symbols collide, it returns true, that's it.

Concerning your last question, I don't understand what you mean by "plot intersection points between them".

Jerryscript
February 29th, 2004, 02:04 PM
Originally posted by Ilyas da Pom
You don't have the choice. HitTest is a 'flat' collision detection. If two symbols collide, it returns true, that's it.
That's why I use a hittest with a check for z-index (_x/_yscale). It's working pretty good now, though I'm just using fake repulsion for the collisions now (see attachment).


Concerning your last question, I don't understand what you mean by "plot intersection points between them".

I'm thinking I might be able to treat each collision as an event, calculate the vector for each sphere upon a collision event, and determine the intesection points of each new vector at that point. This way, you wouldn't need hittest/z-index checks occurring over and over, since you already know when the collision will occur. Just carry the animation through to the next collision and then recalculate vector intersections. Rather than a collision detection every frame, it's only calculated every collision.

I'll post if I get it working, I'm starting with a 9 ball configuration.

Jerryscript
February 29th, 2004, 02:34 PM
For anyone interested in this method, the basic formula is described at the bottom of this page: 3d Algorithms (http://www.sccs.swarthmore.edu/users/00/ceg/computer/3d.html)

Jerryscript
March 2nd, 2004, 01:03 AM
Originally posted by davidchang
well... i dont recommend the hitTest and suggest u use geometry, if u have the (3D) centre of two spheres then the distance between the centre of the two spheres is: Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + Math.pow(z1 - z2, 2)); with the centre of the sphere1 and sphere2 being (x1, y1, z1) and (x2, y2, z3) respectively.

I didnt bother reading the rest of this scale business u got going on.

i hope this helps...

An interesting shortcut, one of those things you can't believe you didn't realize ahead of time: Gamasutra (http://www.gamasutra.com/features/20020118/vandenhuevel_01.htm)

We already know the radii, so we don't need the to compute the square root, instead we can square the sum of the radii, which is much less proccessor intensive, and check it against the sum of the squares as above, but without the squareroot!



collision=(Math.pow(x1-x2,2)+Math.pow(y1-y2,2)+Math.pow(z1-z2,2)<=Math.pow(r1+r2,2))?true:false;

davidchang
March 2nd, 2004, 01:25 AM
....good idea, didn't think of that.