• Status: Solved
• Priority: Medium
• Security: Public
• Views: 446

# Polygon or cube collide

hi,

i need a function that i can put two 3d cubes(or array of poligon) into and an offset and get a boolean return

something like

type t3dpoint= record
x,y,z : extended;
end;

function polycollide(Cube1Points, Cube2Points: array of T3dpointl; OffSet: Extended):boolean;

regards, mark
0
mgazza
• 5
• 3
• 2
• +1
1 Solution

Commented:
And what do you expect to be done inside this function (because there is not a problem only to put parameters into the function without to do anything inside it)
;-))
0

Commented:
function polycollide(Cube1Points, Cube2Points: array of T3dpointl; OffSet: Extended):boolean;
begin
Result := True;
end;

it is not a working function, but it is a very beautiful one
;-))
0

Author Commented:
no i was discribing the function my ideal function it needs to work inside aload of other stuff ,
dont get smart
*sigh*

it will work in conjuntion with this this only finds all objects that are inside a box i need to find out if too poilgons colide

function GetWorldBlock(self:integer;Cube:TWorldCube):Arrayof_TArrayList;
var
i:integer;
temp:array[0..255]of TArrayList;
Nofound:integer;
start:pointer;
begin
nofound:=0; //int the integer;
for i:=0 to high(World_ArrayObjects) do begin
if i<>self then
with World_ArrayObjects[i] do begin
if (Pos.x>Cube.WorldLeft)and(Pos.x<Cube.WorldRight)then //no point in wasting ticks
if (Pos.y>Cube.WorldTop)and(Pos.y<Cube.WorldBottom)then //this way is alot faster
if (Pos.z>Cube.WorldFront)and(Pos.z<Cube.WorldBack)then
if World_ArrayObjects[i].Status=Stdraw then //make sure were alowed to see it
begin
inc(Nofound);
temp[nofound-1]:=World_ArrayObjects[i];
end;
end;
if nofound=256 then  begin//if the buffer fills up dump it
setlength(result,high(result)+nofound);

start:=pointer(longword(@result[0])+(sizeof(TArrayList)*(high(result)-nofound)));
move(Temp,start^,(sizeof(TArrayList)*nofound));        //fast copy .zoom ....

nofound:=0;
end;
end;
if nofound<>0 then begin
//dump some more
setlength(result,high(result)+nofound);

start:=pointer(longword(@result[0])+(sizeof(TArrayList)*(high(result)-nofound)));
move(Temp,start^,(sizeof(TArrayList)*nofound));        //fast copy .zoom ....

nofound:=0;
end;
end;

function CubeFromMesh(MeshIndex:smallint):TWorldCube;
begin
{\$i MeshCubes.inc}
end;

function FindFreeBlock(Wantedpoint:T3dpoint64;MeshBounds:TWorldCube):T3dpoint64;
label
check;
var
i:integer;
MeshSize:TWorldCube;
begin
check:

for i:=0 to high(World_ArrayObjects) do begin
with World_ArrayObjects[i] do
if pos.x=Wantedpoint.x then
if pos.y=Wantedpoint.y then
if pos.z=Wantedpoint.z then
begin
//keep checking until the space is free
inc(wantedpoint.x,random(20));
inc(wantedpoint.y,random(20));
inc(wantedpoint.z,random(20));
goto check;
end;
end;
result:=wantedpoint;
end;

the above function will be using the collide function,

as you can see all that information is usless so stop beging cleaver if you havnt got a soliution i sujest you dont ask
0

Author Commented:
i realy havnt got time to be writing out collision functions. too much work to do

function PointInPoly(APoint : TPoint ; APoly : array of TPoint) : boolean;
Var
i, j : integer;
npol : integer;
begin
Result := false;
npol := length(APoly);
for i := 0 to npol - 1 do begin
j := (i + 1) mod npol;
if ((((APoly[i].Y <= APoint.Y) and (APoint.Y < APoly[j].Y)) or
((APoly[j].Y <= APoint.Y) and (APoint.Y < APoly[i].Y))) and
(APoint.X < (APoly[j].X - APoly[i].X) * (APoint.Y - APoly[i].Y) /
(APoly[j].Y - APoly[i].Y) + APoly[i].X)) then
Result := not Result;
end;
end;

there you are if you like make that function take on T3dpoint and offset

or

make this take on a z value

function CheckCollision(x1, y1,ph,pw,x2, y2,eh,ew: integer): boolean;
const
OFFSET_X = 4; //use 1 for real visual result
OFFSET_Y = 4;
begin
Result := True;

if (y1 + PH - (OFFSET_Y * 2) < y2 + OFFSET_Y) or
(y1 + OFFSET_Y > y2 + Eh - (OFFSET_Y * 2)) or
(x1 + PW - (OFFSET_X * 2) < x2 + OFFSET_X) or
(x1 + OFFSET_X > x2 + EW - (OFFSET_X * 2)) then
Result := False;
end;

0

Commented:
Oh, it is terrible high-mathematical stuff ....
Here is 40 minutes after midnight, so I am very tired to think about high-math even you offer 250,000 points about solution ....
Sorry, I have too much work to do too ....
Emil
0

Commented:
you can check Olivier Renaults collision routines
I've translated the Box project to delphi (it's 2D but could be easily converted to 3D)
there are other examples as well (in c++)
Box delphi version: http://users.volja.net/stdcall/Box.zip
olivier's examples: http://uk.geocities.com/olivier_rebellion/
0

Commented:
OK, to know if 2 3D cubes collide (only for CUBES, not other 3D poligons), look in all 3 cordinates: They collide if and only if some X of the first cube lie between MaxX and MinX of the second one... and the same with other 3 coords... so:

Collide(Cube1, Cube2): boolean;
var CoordXok, CoordYok, CoordYok: boolean;
begin
CoordXok:= ((Cube1.MinX <= Cube2.MaxX) and (Cube1.MaxX >= Cube2.MinX);
CoordYok:= ((Cube1.MinY <= Cube2.MaxY) and (Cube1.MaxY >= Cube2.MinY);
CoordZok:= ((Cube1.MinZ <= Cube2.MaxZ) and (Cube1.MaxZ >= Cube2.MinZ);
result:= CoordXok and CoordYok and CoordZok;
end;

I use it a lot in 2D, but the idea is the same, just without Z coord, and it is VERY fast to know if blocks collide or not.

To use offset in the function, i first should know what does it menas to you: The minimun separation to consider they collide if separation is less that offset? If it is so, then:

Collide(Cube1, Cube2, OffSet): boolean;
var CoordXok, CoordYok, CoordYok: boolean;
begin
CoordXok:= ((Cube1.MinX <= Cube2.MaxX+OffSet) and (Cube1.MaxX >= Cube2.MinX-OffSet);
CoordYok:= ((Cube1.MinY <= Cube2.MaxY+OffSet) and (Cube1.MaxY >= Cube2.MinY-OffSet);
CoordZok:= ((Cube1.MinZ <= Cube2.MaxZ+OffSet) and (Cube1.MaxZ >= Cube2.MinZ-OffSet);
result:= CoordXok and CoordYok and CoordZok;
end;

Hope it was your goal to get this function, correctme if don't.
0

Commented:
Ops! some typo error in my last post, all of them trivial... "function" keyword missing, and 3rd variable name is CoodZok, not CoordYok, obviously!
0

Author Commented:
thanks alot thats just what i was looking for :D
0

Author Commented:
humm there seams to be a problem wwhen the cube1 is coliding on the top right corner on cube2

function CubeCollide(Cube1, Cube2:TWorldCube; OffSet: Extended): boolean;
var CoordXok, CoordYok, CoordZok: boolean;
begin
CoordXok:= ((Cube1.WorldLeft <= Cube2.WorldRight+OffSet) and (Cube1.WorldRight >= Cube2.WorldLeft-OffSet));
CoordYok:= ((Cube1.WorldTop <= Cube2.WorldBottom+OffSet) and (Cube1.WorldTop >= Cube2.WorldTop-OffSet));
CoordZok:= ((Cube1.WorldFront <= Cube2.WorldBack+OffSet) and (Cube1.WorldFront >= Cube2.WorldFront-OffSet));
result:= CoordXok and CoordYok and CoordZok;
end;

{
........
.\        \
. \   wt   \
.  \........\
.wl'        '
\  '  wf    '
\ '        '
\'........'
}
procedure TForm1.FormClick(Sender: TObject);
var
c1,c2:TWorldCube;
begin
c1.WorldLeft:=shape1.Left;
c1.WorldRight:=shape1.Left+shape1.Width;
c1.WorldTop:=shape1.Top;
c1.WorldBottom:=shape1.Top+shape1.Height;
c1.WorldFront:=0;
c1.WorldBack:=0; //depth of 10

c2.WorldLeft:=shape2.Left;
c2.WorldRight:=shape2.Left+shape2.Width;
c2.WorldTop:=shape2.Top;
c2.WorldBottom:=shape2.Top+shape2.Height;
c2.WorldFront:=0;
c2.WorldBack:=0; //depth of 10
if CubeCollide(c1,c2,0) then showmessage('hit');
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Shift=[ssalt] then begin
shape1.Left:=x;
shape1.Top:=y;
end;
end;
0

Author Commented:
humm judt got time to write my own function:D

this one works and well fast(when theres no colision)
(if theres 3000 objects and only 1 of them hit get wat i mean)

function InBetween(N,Alpha,Beta:integer):boolean;
begin
result:=(n>=alpha) and (n<=Beta);
end;

function CubeCollide(Cube1, Cube2:TWorldCube; OffSet: Integer): boolean;
begin
result:=false;
if
Inbetween(cube1.WorldLeft, cube2.WorldLeft-OffSet, cube2.WorldRight+OffSet)
or
Inbetween(cube1.WorldRight, cube2.WorldLeft-OffSet, cube2.WorldRight+OffSet)
then
if
Inbetween(cube1.WorldTop, cube2.WorldTop-OffSet, cube2.WorldBottom+OffSet)
or
Inbetween(cube1.WorldBottom, cube2.WorldTop-OffSet, cube2.WorldBottom+OffSet)
then
if
Inbetween(cube1.WorldFront, cube2.WorldFront-OffSet, cube2.WorldBack+OffSet)
or
Inbetween(cube1.WorldBack, cube2.WorldFront-OffSet, cube2.WorldBack+OffSet)
then result:=true;

end;
{
........
.\        \
. \   wt   \
.  \........\
.wl'        '
\  '  wf    '
\ '        '
\'........'
}
procedure TForm1.FormClick(Sender: TObject);
var
c1,c2:TWorldCube;
begin
c1.WorldLeft:=shape1.Left;
c1.WorldRight:=shape1.Left+shape1.Width;
c1.WorldTop:=shape1.Top;
c1.WorldBottom:=shape1.Top+shape1.Height;
c1.WorldFront:=0;
c1.WorldBack:=0; //depth of 10

c2.WorldLeft:=shape2.Left;
c2.WorldRight:=shape2.Left+shape2.Width;
c2.WorldTop:=shape2.Top;
c2.WorldBottom:=shape2.Top+shape2.Height;
c2.WorldFront:=0;
c2.WorldBack:=0; //depth of 10
if CubeCollide(c1,c2,0) then showmessage('hit');
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Shift=[ssalt] then begin
shape1.Left:=x;
shape1.Top:=y;
end;
end;
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.