Link to home
Start Free TrialLog in
Avatar of mgazza
mgazzaFlag for United Kingdom of Great Britain and Northern Ireland

asked on

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
Avatar of esoftbg
esoftbg
Flag of Bulgaria image

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)
;-))
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
;-))
Avatar of mgazza

ASKER

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
Avatar of mgazza

ASKER

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;

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
Avatar of Lee_Nover
Lee_Nover

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/
ASKER CERTIFIED SOLUTION
Avatar of Sergio_Hdez
Sergio_Hdez

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ops! some typo error in my last post, all of them trivial... "function" keyword missing, and 3rd variable name is CoodZok, not CoordYok, obviously!
Avatar of mgazza

ASKER

thanks alot thats just what i was looking for :D
Avatar of mgazza

ASKER

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;
Avatar of mgazza

ASKER

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;