Page 1 of 1

Problems with RayCast

Posted: Sat Aug 24, 2013 8:46 pm
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

Re: Problems with RayCast

Posted: Sat Aug 24, 2013 10:13 pm
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

Re: Problems with RayCast

Posted: Sat Aug 24, 2013 10:52 pm
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()

Re: Problems with RayCast

Posted: Sat Aug 24, 2013 11:08 pm
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.

Re: Problems with RayCast

Posted: Sat Aug 24, 2013 11:22 pm
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

Re: Problems with RayCast

Posted: Sat Aug 24, 2013 11:41 pm
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?

Re: Problems with RayCast

Posted: Mon Aug 26, 2013 10:03 pm
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

Re: Problems with RayCast

Posted: Mon Aug 26, 2013 11:43 pm
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

Re: Problems with RayCast

Posted: Tue Aug 27, 2013 3:05 pm
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.

Re: Problems with RayCast

Posted: Tue Aug 27, 2013 5:38 pm
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.

Re: Problems with RayCast

Posted: Fri Mar 06, 2020 7:11 pm
by Mesa
Updated return value for Raycast() =-1.