Problems with RayCast

Everything related to 3D programming
MightyMAC
User
User
Posts: 42
Joined: Thu Apr 11, 2013 5:47 pm

Problems with RayCast

Post by MightyMAC »

Hi guys,

I'm currently doing some test with RayCast() and it doesn't work as (I) expected. In the following code I try to test connections of waypoints via RayCast and it seems they can (almost) all see each other. Mustn't the ray be interrupted by the walls? Am I doing something wrong? And why does the RayCast return 0? I think it should only return 5 or 8 (the wall entities).

Code: Select all

InitEngine3D()
InitSprite()

Structure Str_PathConnection
  *Waypoint
  Distance.d
EndStructure

Structure Str_PathWaypoint
  Entity.l
  List Connection.Str_PathConnection()
EndStructure

Global NewList Waypoint.Str_PathWaypoint()

#WallPick = 1 << 1

;WorldDebug(#PB_World_DebugEntity)
    
OpenWindow(0,100,100,800,600,"Test")
OpenWindowedScreen(WindowID(0),0,0,800,600)

; Camera
CreateCamera(1,0,0,100,100)
MoveCamera(1,0,100,100,#PB_Relative)
RotateCamera(1,-50,0,0)

; Materials
CreateTexture(0,256,256)
StartDrawing(TextureOutput(0))
  Box(0,0,255,255,RGB(200,0,0))
StopDrawing()

CreateTexture(1,256,256)
StartDrawing(TextureOutput(1))
  Box(0,0,255,255,RGB(0,0,200))
StopDrawing()

CreateTexture(2,256,256)
StartDrawing(TextureOutput(2))
  Box(0,0,255,255,RGB(0,200,200))
StopDrawing()

CreateMaterial(0,TextureID(0))
CreateMaterial(1,TextureID(1))
CreateMaterial(2,TextureID(2))

; Floor
CreatePlane(2,100,100,10,10,1,1)
CreateEntity(3,MeshID(2),MaterialID(0))

; Walls
CreateCube(4,10)
CreateEntity(5,MeshID(4),MaterialID(1),0,0,0,#WallPick)
ScaleEntity(5,5,2,0.3)
CreateEntity(8,MeshID(4),MaterialID(1),20,0,0,#WallPick)
ScaleEntity(8,0.3,2,5)

; Light
CreateLight(6,RGB(255,255,255),0,100,0)
AmbientColor(RGB(25, 25, 25))

Global WaypointMesh=CreateCylinder(#PB_Any,0.2,15)

Hero=CreateEntity(#PB_Any,MeshID(WaypointMesh),MaterialID(2),10,0,20,0)
ScaleEntity(Hero,3,1,10)

Aim=CreateEntity(#PB_Any,MeshID(WaypointMesh),MaterialID(2),0,0,-20,0)

Procedure Pathfinding_Init(StartMesh,AimMesh)
  Protected *TempWaypoint.Str_PathWaypoint
  Protected LineCount=0
  
  ; Add Start and Aim to the waypoint graph
  AddElement(Waypoint())
  Waypoint()\Entity=StartMesh
  AddElement(Waypoint())
  Waypoint()\Entity=AimMesh
  
  ; Check all connections between waypoints
  ForEach Waypoint()
    ClearList(Waypoint()\Connection())
    *TempWaypoint=@Waypoint()
    PushListPosition(Waypoint())
    ForEach Waypoint()
      If @Waypoint()<>*TempWaypoint
        Res=RayCast(EntityX(*TempWaypoint\Entity),EntityY(*TempWaypoint\Entity)+4,EntityZ(*TempWaypoint\Entity),EntityX(Waypoint()\Entity),EntityY(Waypoint()\Entity)+4,EntityZ(Waypoint()\Entity),#WallPick)
        Debug "Cast ("+StrD(EntityX(*TempWaypoint\Entity))+", "+StrD(EntityY(*TempWaypoint\Entity))+", "+StrD(EntityZ(*TempWaypoint\Entity))+") - ("+StrD(EntityX(Waypoint()\Entity))+", "+StrD(EntityY(Waypoint()\Entity))+", "+StrD(EntityZ(Waypoint()\Entity))+")"
        If Res<0
          AddElement(*TempWaypoint\Connection())
          *TempWaypoint\Connection()\Waypoint=@Waypoint()
          *TempWaypoint\Connection()\Distance=Sqr(Pow(EntityX(*TempWaypoint\Entity)+EntityX(Waypoint()\Entity),2.0) + Pow(EntityY(*TempWaypoint\Entity)+EntityY(Waypoint()\Entity),2.0) + Pow(EntityZ(*TempWaypoint\Entity)+EntityZ(Waypoint()\Entity),2.0))
          CreateLine3D(100+LineCount,EntityX(*TempWaypoint\Entity),EntityY(*TempWaypoint\Entity)+4,EntityZ(*TempWaypoint\Entity),RGB(255,255,255),EntityX(Waypoint()\Entity),EntityY(Waypoint()\Entity)+4,EntityZ(Waypoint()\Entity),RGB(255,255,255))
          LineCount+1
          Debug "Connection!"
        Else
          Debug "No Connection - Wall: "+Str(Res)
        EndIf
      EndIf
    Next
    PopListPosition(Waypoint())
  Next
EndProcedure

Procedure Add_Waypoint(x.d,y.d,z.d)
  AddElement(Waypoint())
  Waypoint()\Entity=CreateEntity(#PB_Any,MeshID(WaypointMesh),MaterialID(1),x,y,z)
EndProcedure

; Add some waypoints
Add_Waypoint(30,0,10)
Add_Waypoint(-30,0,10)
Add_Waypoint(-30,0,-30)

; Render world has to be called once, otherwise RayCast does not work
RenderWorld()

Pathfinding_Init(Hero,Aim)

; Create overlay sprite for text output
Overlay=CreateSprite(#PB_Any,800,600)
StartDrawing(SpriteOutput(Overlay))
  DrawingMode(#PB_2DDrawing_Transparent)
  ForEach Waypoint()
    DrawText(CameraProjectionX(1,EntityX(Waypoint()\Entity),EntityY(Waypoint()\Entity),EntityZ(Waypoint()\Entity)),CameraProjectionY(1,EntityX(Waypoint()\Entity),EntityY(Waypoint()\Entity),EntityZ(Waypoint()\Entity)),"("+StrD(EntityX(Waypoint()\Entity))+", "+StrD(EntityY(Waypoint()\Entity))+", "+StrD(EntityZ(Waypoint()\Entity))+")")
  Next
StopDrawing()

; Main loop
Repeat
  RenderWorld()
  DisplayTransparentSprite(Overlay,0,0)
  FlipBuffers()
Until WindowEvent()=#PB_Event_CloseWindow
Cheers
MAC
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Problems with RayCast

Post by Samuel »

Hello MightyMAC,

I've never done much work with RayCast(), but I might see a little problem.
The help files say RayCast() returns nonzero if it came in contact with an object.
In your code you only check if the value is less than ZERO. So, you could try changing it to greater than and less than.

Code: Select all

        Res=RayCast(EntityX(*TempWaypoint\Entity),EntityY(*TempWaypoint\Entity)+4,EntityZ(*TempWaypoint\Entity),EntityX(Waypoint()\Entity),EntityY(Waypoint()
        If Res<>0
          Debug "Connection!"
        Else
          Debug "No Connection - Wall: "+Str(Res)
        EndIf
User avatar
Comtois
Addict
Addict
Posts: 1429
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Problems with RayCast

Post by Comtois »

Well, then doc is wrong.

RayCast() return entity's number, it can be 0. So doc should be
Returns -1 if the ray has collided with any object.

MightyMAC,

Add RenderWorld() Before RayCast()
Please correct my english
http://purebasic.developpez.com/
MightyMAC
User
User
Posts: 42
Joined: Thu Apr 11, 2013 5:47 pm

Re: Problems with RayCast

Post by MightyMAC »

I already have a RenderWorld() before the call of the procedure (Pathfinding_Init()) where the RayCast is done:

Code: Select all

; Render world has to be called once, otherwise RayCast does not work
RenderWorld()
but even if I put it in the loop right before the RayCast() call it doesn't change a thing.
User avatar
Comtois
Addict
Addict
Posts: 1429
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Problems with RayCast

Post by Comtois »

I get this with your code
Cast (30, 0, 10) - (-30, 0, 10)
No Connection - Wall: 8
Cast (30, 0, 10) - (-30, 0, -30)
No Connection - Wall: 8
Cast (30, 0, 10) - (10, 0, 20)
Connection!
Cast (30, 0, 10) - (0, 0, -20)
Connection!
Cast (-30, 0, 10) - (30, 0, 10)
Connection!
Cast (-30, 0, 10) - (-30, 0, -30)
Connection!
Cast (-30, 0, 10) - (10, 0, 20)
Connection!
Cast (-30, 0, 10) - (0, 0, -20)
Connection!
Cast (-30, 0, -30) - (30, 0, 10)
Connection!
Cast (-30, 0, -30) - (-30, 0, 10)
Connection!
Cast (-30, 0, -30) - (10, 0, 20)
No Connection - Wall: 5
Cast (-30, 0, -30) - (0, 0, -20)
Connection!
Cast (10, 0, 20) - (30, 0, 10)
No Connection - Wall: 8
Cast (10, 0, 20) - (-30, 0, 10)
No Connection - Wall: 0
Cast (10, 0, 20) - (-30, 0, -30)
No Connection - Wall: 5
Cast (10, 0, 20) - (0, 0, -20)
No Connection - Wall: 5
Cast (0, 0, -20) - (30, 0, 10)
No Connection - Wall: 8
Cast (0, 0, -20) - (-30, 0, 10)
No Connection - Wall: 0
Cast (0, 0, -20) - (-30, 0, -30)
No Connection - Wall: 0
Cast (0, 0, -20) - (10, 0, 20)
No Connection - Wall: 5
if i add RenderWorld() before RayCast(), i get this :
Cast (30, 0, 10) - (-30, 0, 10)
No Connection - Wall: 8
Cast (30, 0, 10) - (-30, 0, -30)
No Connection - Wall: 8
Cast (30, 0, 10) - (10, 0, 20)
Connection!
Cast (30, 0, 10) - (0, 0, -20)
Connection!
Cast (-30, 0, 10) - (30, 0, 10)
Connection!
Cast (-30, 0, 10) - (-30, 0, -30)
Connection!
Cast (-30, 0, 10) - (10, 0, 20)
Connection!
Cast (-30, 0, 10) - (0, 0, -20)
Connection!
Cast (-30, 0, -30) - (30, 0, 10)
Connection!
Cast (-30, 0, -30) - (-30, 0, 10)
Connection!
Cast (-30, 0, -30) - (10, 0, 20)
No Connection - Wall: 5
Cast (-30, 0, -30) - (0, 0, -20)
Connection!
Cast (10, 0, 20) - (30, 0, 10)
No Connection - Wall: 8
Cast (10, 0, 20) - (-30, 0, 10)
Connection!
Cast (10, 0, 20) - (-30, 0, -30)
No Connection - Wall: 5
Cast (10, 0, 20) - (0, 0, -20)
No Connection - Wall: 5
Cast (0, 0, -20) - (30, 0, 10)
No Connection - Wall: 8
Cast (0, 0, -20) - (-30, 0, 10)
Connection!
Cast (0, 0, -20) - (-30, 0, -30)
Connection!
Cast (0, 0, -20) - (10, 0, 20)
No Connection - Wall: 5
Please correct my english
http://purebasic.developpez.com/
MightyMAC
User
User
Posts: 42
Joined: Thu Apr 11, 2013 5:47 pm

Re: Problems with RayCast

Post by MightyMAC »

Yes, ok, the 0 is no longer recognized as a wall, but as you can see in the viewport when the code is executed, there are only 3 waypoints that should see each other. But the program Returns way to much Connections. The rays go straight through the walls. Is there something I overlooked?
User avatar
Comtois
Addict
Addict
Posts: 1429
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Problems with RayCast

Post by Comtois »

I did some tests, the problem also appears with RayPick (). at this stage I do not know if bug come from PureBasic or ogre ?

Try to change scale value for x

Code: Select all

ScaleEntity(5,58,20,3) ; Result change if 59 instead of 58

Code: Select all

InitEngine3D(3)
InitSprite()

OpenWindow(0,100,100,800,600,"Test")
OpenWindowedScreen(WindowID(0),0,0,800,600)

WorldDebug(#PB_World_DebugEntity)
Structure Vector3
  x.f
  y.f
  z.f
EndStructure

Dim WayPoint.Vector3(10)

; Camera
CreateCamera(1,0,0,100,100)
MoveCamera(1,0,100,100,#PB_Relative)
RotateCamera(1,-50,0,0)

; Materials
CreateTexture(1,256,256)
StartDrawing(TextureOutput(1))
Box(0,0,255,255,RGB(0,0,200))
StopDrawing()


CreateMaterial(1,TextureID(1))

; Walls
CreateCube(4,1)
CreateEntity(5,MeshID(4),MaterialID(1),0,0,0, 1)
ScaleEntity(5,58,20,3) ; Result change if 59 instead of 58

; Light
CreateLight(6,RGB(255,255,255),0,100,0)
AmbientColor(RGB(25, 25, 25))

; Add some waypoints
Waypoint(1)\x = 0
Waypoint(1)\y = 0
Waypoint(1)\z = -20

Waypoint(3)\x = -30
Waypoint(3)\y = 0
Waypoint(3)\z = 10

d = 3 ; result change if d = 1 and f = 3
f = 1 ; 

RenderWorld()

ResPick = RayPick(Waypoint(d)\x, Waypoint(d)\y+4, Waypoint(d)\z, Waypoint(f)\x, Waypoint(f)\y+4, Waypoint(f)\z, 1)

If ResPick<0
  
  CreateLine3D(100+LineCount,Waypoint(d)\x, Waypoint(d)\y+4, Waypoint(d)\z, RGB(0,255,0), 
               Waypoint(f)\x, Waypoint(f)\y+4, Waypoint(f)\z, RGB(0,255,0))
  
Else
  CreateLine3D(100+LineCount,Waypoint(d)\x, Waypoint(d)\y+4, Waypoint(d)\z, RGB(255,0,0), 
               Waypoint(f)\x, Waypoint(f)\y+4, Waypoint(f)\z, RGB(255,0,0))
EndIf  

Repeat
  RenderWorld()
  FlipBuffers()
Until WindowEvent()=#PB_Event_CloseWindow
Please correct my english
http://purebasic.developpez.com/
User avatar
Comtois
Addict
Addict
Posts: 1429
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Problems with RayCast

Post by Comtois »

no bug, RayPick() or RayCast() need a direction not a destination

Code: Select all

InitEngine3D(3)
InitSprite()

OpenWindow(0,100,100,800,600,"Test")
OpenWindowedScreen(WindowID(0),0,0,800,600)

WorldDebug(#PB_World_DebugEntity)
Structure Vector3
  x.f
  y.f
  z.f
EndStructure

Dim WayPoint.Vector3(10)

; Camera
CreateCamera(1,0,0,100,100)
MoveCamera(1,0,100,100,#PB_Relative)
RotateCamera(1,-50,0,0)

; Materials
CreateTexture(1,256,256)
StartDrawing(TextureOutput(1))
Box(0,0,255,255,RGB(0,0,200))
StopDrawing()


CreateMaterial(1,TextureID(1))

; Walls
CreateCube(4,1)
CreateEntity(5,MeshID(4),MaterialID(1),0,0,0, 1)
ScaleEntity(5,50,20,3) 

; Light
CreateLight(6,RGB(255,255,255),0,100,0)
AmbientColor(RGB(25, 25, 25))

; Add some waypoints
Waypoint(1)\x = 0
Waypoint(1)\y = 0
Waypoint(1)\z = -20

Waypoint(3)\x = -30
Waypoint(3)\y = 0
Waypoint(3)\z = 10

d = 1 ;
f = 3 ;

Direction.Vector3
Direction\x = Waypoint(f)\x - Waypoint(d)\x
Direction\y = Waypoint(f)\y - Waypoint(d)\y
Direction\z = Waypoint(f)\z - Waypoint(d)\z

RenderWorld()

ResPick = RayPick(Waypoint(d)\x, Waypoint(d)\y+4, Waypoint(d)\z, Direction\x, Direction\y+4, Direction\z, 1)

If ResPick<0
  
  CreateLine3D(100+LineCount,Waypoint(d)\x, Waypoint(d)\y+4, Waypoint(d)\z, RGB(0,255,0),
               Waypoint(f)\x, Waypoint(f)\y+4, Waypoint(f)\z, RGB(0,255,0))
  
Else
  CreateLine3D(100+LineCount,Waypoint(d)\x, Waypoint(d)\y+4, Waypoint(d)\z, RGB(255,0,0),
               Waypoint(f)\x, Waypoint(f)\y+4, Waypoint(f)\z, RGB(255,0,0))
EndIf 

Repeat
  RenderWorld()
  FlipBuffers()
Until WindowEvent()=#PB_Event_CloseWindow
Please correct my english
http://purebasic.developpez.com/
MightyMAC
User
User
Posts: 42
Joined: Thu Apr 11, 2013 5:47 pm

Re: Problems with RayCast

Post by MightyMAC »

Yeah, that's it. And it's also done in the RayCast example file. I think the RayCast chapter in the manual should be updated. But I have another problem with it. It seems the picking mask does not filter the walls only but returns everything it finds.

If I change my code to this:

Code: Select all

        RenderWorld()
        Res=RayCast(EntityX(*TempWaypoint\Entity),EntityY(*TempWaypoint\Entity)+4,EntityZ(*TempWaypoint\Entity),EntityX(Waypoint()\Entity)-EntityX(*TempWaypoint\Entity),(EntityY(Waypoint()\Entity)+4)-(EntityY(*TempWaypoint\Entity)+4),EntityZ(Waypoint()\Entity)-EntityZ(*TempWaypoint\Entity),#WallPick)
        Debug "Cast ("+StrD(EntityX(*TempWaypoint\Entity))+", "+StrD(EntityY(*TempWaypoint\Entity))+", "+StrD(EntityZ(*TempWaypoint\Entity))+") - ("+StrD(EntityX(Waypoint()\Entity))+", "+StrD(EntityY(Waypoint()\Entity))+", "+StrD(EntityZ(Waypoint()\Entity))+")"
        If Res<>8 And Res<>5
          AddElement(*TempWaypoint\Connection())
          *TempWaypoint\Connection()\Waypoint=@Waypoint()
          *TempWaypoint\Connection()\Distance=Sqr(Pow(EntityX(*TempWaypoint\Entity)+EntityX(Waypoint()\Entity),2.0) + Pow(EntityY(*TempWaypoint\Entity)+EntityY(Waypoint()\Entity),2.0) + Pow(EntityZ(*TempWaypoint\Entity)+EntityZ(Waypoint()\Entity),2.0))
          CreateLine3D(100+LineCount,EntityX(*TempWaypoint\Entity),EntityY(*TempWaypoint\Entity)+4,EntityZ(*TempWaypoint\Entity),RGB(255,255,255),EntityX(Waypoint()\Entity),EntityY(Waypoint()\Entity)+4,EntityZ(Waypoint()\Entity),RGB(255,255,255))
          LineCount+1
          Debug "Connection!"
        Else
          Debug "No Connection - Wall: "+Str(Res)
        EndIf
it works like expected. But if I use

Code: Select all

        If Res<0
it also returns my waypoint meshes as walls even if they don't have the #WallPick picking mask applied at creation time.
User avatar
Comtois
Addict
Addict
Posts: 1429
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Problems with RayCast

Post by Comtois »

You need to add a mask here

Code: Select all

Procedure Add_Waypoint(x.d,y.d,z.d)
  AddElement(Waypoint())
  Waypoint()\Entity=CreateEntity(#PB_Any,MeshID(WaypointMesh),MaterialID(1),x,y,z,0)
EndProcedure
Fixed RayCast() for next release.
Please correct my english
http://purebasic.developpez.com/
Mesa
Enthusiast
Enthusiast
Posts: 349
Joined: Fri Feb 24, 2012 10:19 am

Re: Problems with RayCast

Post by Mesa »

Updated return value for Raycast() =-1.
Post Reply