Solved

# Polygon or cube collide

Posted on 2004-10-06
424 Views
Last Modified: 2010-05-18
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
Question by:mgazza
• 5
• 3
• 2
• +1
11 Comments

LVL 12

Expert Comment

ID: 12242107
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

LVL 12

Expert Comment

ID: 12242134
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

LVL 1

Author Comment

ID: 12242672
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

LVL 1

Author Comment

ID: 12242711
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

LVL 12

Expert Comment

ID: 12242978
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

LVL 12

Expert Comment

ID: 12245571
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

LVL 6

Accepted Solution

Sergio_Hdez earned 300 total points
ID: 12248063
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

LVL 6

Expert Comment

ID: 12248086
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

LVL 1

Author Comment

ID: 12249147
thanks alot thats just what i was looking for :D
0

LVL 1

Author Comment

ID: 12262371
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

LVL 1

Author Comment

ID: 12270635
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

## Join & Write a Comment Already a member? Login.

### Suggested Solutions

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have toā¦
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy reā¦
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the fileā¦

#### 707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

#### Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!