Solved

Polygon or cube collide

Posted on 2004-10-06
11
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
Comment
Question by:mgazza
  • 5
  • 3
  • 2
  • +1
11 Comments
 
LVL 12

Expert Comment

by:esoftbg
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

by:esoftbg
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

by:mgazza
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

by:mgazza
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

by:esoftbg
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
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 12

Expert Comment

by:Lee_Nover
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

by:
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

by:Sergio_Hdez
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

by:mgazza
ID: 12249147
thanks alot thats just what i was looking for :D
0
 
LVL 1

Author Comment

by:mgazza
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

by:mgazza
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

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

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.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now