Code archives/3D Graphics - Misc/LineOfSight3D

This code has been declared by its author to be Public Domain code.

Download source code

LineOfSight3D by fredborg2002
You can use this function to test whether one entity can see another entity. It is possible to define how far the entity can see, and how wide it's field of view is.

The function uses LinePick, so remember to set the PickMode of the entities!

The actual function is at the bottom of the example, the rest is not needed to use the function.

Use as you please.
;
; LineOfSight3D - Example usage
;
; Created by Mikkel Fredborg
;

Graphics3D 640,480 
SetBuffer BackBuffer() 

;setup light
AmbientLight 128,128,128
light = CreateLight()

;create a camera
camera=CreateCamera()
PositionEntity camera,0,10,0
RotateEntity camera,90,0,0
CameraProjMode camera,2
CameraZoom camera,0.05

;create a wall
wall = CreateCube()
EntityColor wall,128,128,128
ScaleEntity wall,5,1,1
PositionEntity wall,0,0,-4
EntityPickMode wall,2

;create two targets
c2=CreateSphere() 
EntityColor c2,128,50,50
PositionEntity c2,2,0,0
EntityPickMode c2,2

c4=CreateSphere() 
EntityColor c4,128,50,50
PositionEntity c4,2,0,-6
EntityPickMode c4,2

; create observer
c3=CreateCone() 
RotateMesh c3,90,0,0
EntityColor c3,50,128,90

; viewcone dummy
vd# = 10.0 
va# = 90.0

Global viewcone = CreateDisc(va/10,c3,1,-va/2.0,va/2.0)
EntityColor viewcone,0,50,64
EntityFX viewcone,1

lastva# = va#
lastvd# = vd#

While Not KeyDown( 1 ) 

	; controls
	TurnEntity c3,0,(KeyDown(203)-KeyDown(205)),0 		; Left/Right arrow rotates
	MoveEntity c3,0,0,(KeyDown(200)-KeyDown(208))*0.1	; Up/Down arrow moves forward and backward
	
	vd# = vd#+(KeyDown(201)-KeyDown(209))*0.1			; Page Up/Down Alters view range
	If vd<1.0 Then vd = 1.0

	va# = va#+(KeyDown(210)-KeyDown(211))				; Insert/Delete alters view angle
	If va<  1.0 Then va =   1.0
	If va>360.0 Then va = 360.0

	; update viewcone mesh, if changes have been made
	If va<>lastva
		FreeEntity viewcone
		viewcone = CreateDisc(va/10,c3,1.0,-va/2.0,va/2.0)
		EntityColor viewcone,0,50,64
		EntityFX viewcone,1
		
		lastva = va
		lastvd = vd
	End If

	ScaleEntity viewcone,vd,vd,vd

	UpdateWorld
	RenderWorld 

	Text 320,10,"Arrows - move | Page Up/Down - view range | Insert\Delete - view angle",True

	visible1 = LineOfSight3D(c3,c2,vd,va)
	visible2 = LineOfSight3D(c3,c4,vd,va)
	
	If visible1
		Text 320,40,"Observer can see target 1",True
		CameraProject camera,EntityX(c3,True),EntityY(c3,True),EntityZ(c3,True)
		x0 = ProjectedX()
		y0 = ProjectedY()
			
		CameraProject camera,EntityX(c2,True),EntityY(c2,True),EntityZ(c2,True)
		x1 = ProjectedX()
		y1 = ProjectedY()

		Line(x0,y0,x1,y1)				
	Else
		Text 320,40,"Observer can NOT see target 1",True
		CameraProject camera,EntityX(c3,True),EntityY(c3,True),EntityZ(c3,True)
		x0 = ProjectedX()
		y0 = ProjectedY()
			
		CameraProject camera,EntityX(c2,True),EntityY(c2,True),EntityZ(c2,True)
		x1 = ProjectedX()
		y1 = ProjectedY()

		DottedLine(x0,y0,x1,y1)
	End If
	
	If visible2
		Text 320,50,"Observer can see target 2",True
			
		CameraProject camera,EntityX(c3,True),EntityY(c3,True),EntityZ(c3,True)
		x0 = ProjectedX()
		y0 = ProjectedY()
			
		CameraProject camera,EntityX(c4,True),EntityY(c4,True),EntityZ(c4,True)
		x1 = ProjectedX()
		y1 = ProjectedY()

		Line(x0,y0,x1,y1)
	Else
		Text 320,50,"Observer can NOT see target 2",True
		CameraProject camera,EntityX(c3,True),EntityY(c3,True),EntityZ(c3,True)
		x0 = ProjectedX()
		y0 = ProjectedY()
			
		CameraProject camera,EntityX(c4,True),EntityY(c4,True),EntityZ(c4,True)
		x1 = ProjectedX()
		y1 = ProjectedY()

		DottedLine(x0,y0,x1,y1)
	End If

	Text 320,440,"View Range - "+vd+"| View Angle - "+va,True

	Flip 

Wend 
End 

Function DottedLine(stx#,sty#,enx#,eny#,dotlength=5)

	mvx#=Stx-enx:mvy#=sty-eny
	If mvx<0 mvx=-mvx
	If mvy<0 mvy=-mvy
	If mvy>mvx mv#=mvy Else mv#=mvx
	stpx#=(mvx/mv):If Stx>enx stpx=-stpx
	stpy#=(mvy/mv):If Sty>eny stpy=-stpy

	; Calculate the color of the line
	c = (ColorRed()*256*256)+(ColorGreen()*256)+ColorBlue()
	LockBuffer GraphicsBuffer()
	For nc=0 To Floor(mv)
		If stx>0 And stx<GraphicsWidth()-1
			If sty>0 And sty<GraphicsHeight()-1
				If (Int(nc/dotlength) Mod 2) = 0
					WritePixelFast stx,sty,c
				End If
			End If
		End If
			
		stx=stx+stpx
		sty=sty+stpy
	Next
	UnlockBuffer GraphicsBuffer()

End Function

Function CreateDisc(segments=8,parent=0,radius#=1.0,anglemin#=0.0,anglemax#=360.0)
	
	If segments<1 Then segments = 1
	
	disc = CreateMesh(parent)
	surf = CreateSurface(disc)
	
	v0 = AddVertex(surf,0,0,0)
	v1 = AddVertex(surf,Sin(anglemin)*radius,0,Cos(anglemin)*radius)
	
	anglestep# = (anglemax-anglemin)/Float(segments)
	
	For segment = 1 To segments
		angle# = anglemin+(anglestep*segment)
		v2 = AddVertex(surf,Sin(angle)*radius,0,Cos(angle)*radius)
		AddTriangle(surf,v0,v1,v2)
		v1 = v2
	Next

	Return disc

End Function

;
; LineOfSight3D()
;
; Usage:
;	observer	= Entity that is looking
;	target		= Entity that the observer is looking for
;	viewrange	= How far can the observer see (in units)
;	viewangle	= How wide is the view of the observer (in degrees)
;
; Created by Mikkel Fredborg - Use as you please
;
Function LineOfSight3D(observer,target,viewrange#=10.0,viewangle# = 90.0)

	;distance between observer and target
	Local dist# = EntityDistance(observer,target)

	;check if the target is within viewrange 
	If dist<=viewrange
		
		;observer vector
		TFormVector 0,0,1,observer,0
		Local ox# = TFormedX()
		Local oy# = TFormedY()
		Local oz# = TFormedZ()
	
		;pick vector
		Local dx# = (EntityX(target,True)-EntityX(observer,True))/dist#
		Local dy# = (EntityY(target,True)-EntityY(observer,True))/dist#
		Local dz# = (EntityZ(target,True)-EntityZ(observer,True))/dist#

		;dot product
		Local dot# = ox*dx + oy*dy + oz*dz

		;check if the target is within the viewangle
		If dot => Cos(viewangle/2.0)
			; check if something is blocking the view
			If LinePick(EntityX(observer,True),EntityY(observer,True),EntityZ(observer,True),dx*viewrange,dy*viewrange,dz*viewrange,0.01)=target
				; observer can see target
				Return True
			End If
		End If
		
	End If

	; observer cannot see target	
	Return False

End Function

Comments

patmaba2006
superb function


Phoenix2006
Great!


harko2007
Hey that is a great function. As a beginner at Blitz3d, I find that stuff really helpful.


Code Archives Forum