3DPathfinding editor for TECNO (need hard testing)

Blitz3D Forums/Blitz3D Programming/3DPathfinding editor for TECNO (need hard testing)

@jfk,

Ok, I finished the 3d pathfinding editor,

but the code is certainly > dirty <

I'm starting to cleaning it up to adapt it to my game
but I don't know when I will finish or how much generic
it will be when I finish.
So I decided to post the code as it is now ...

The best I can tell you is to see the help with F1

good luck :)
Paolo.

AppTitle "3DPathfinding editor by Paolo Cosentino"


Graphics3D 800,600,16,2

Function interpolate#(v#,a#,b#,c#,d#)
Return c+(((v-a)*(d-c))/(b-a))
End Function


AmbientLight 255,255,255


Global cam_player=CreateCamera()
	CameraRange cam_player,.01,200
	RotateEntity cam_player,0,90,0
	EntityRadius cam_player,.8,1.9

;----------------------------------------------
;--------- LOAD A LEVEL HERE --------------

;The 3D space is empty so is better if you load
;something to understand where you are.



;----------------------------------------------
;----------------------------------------------



font=LoadFont("arial",15,0,0,0)
SetFont font


;***************************************
;------- PATHFINDING --------
reset=True
Global node1=0
Global node2=0


Global path_picked=0
Global path_editing=1
Global path_nodeselected=-1
Global path_total$=""
Global path_maxnodes=50 ;999

Dim paths1(path_maxnodes,5)
	;a,0 = Visual of NODE (it should contain a pivot to retreive POSITION of the NODE)
	;a,1 = In Open or Closed list, =0 Default , =1 in Open , =2 in Closed
	;a,2 = F  (it is G+H)
	;a,3 = G ,distance from actual node to before node
	;a,4 = H ,distance from actual node to detination node
	;a,5 = Parent of the node
	
Dim paths1b$(path_maxnodes)
	;a = Contain a string with the nodes that are linked with the actual node (00102030 ...)

Function LOAD_NODESFILE(f$)
	file=ReadFile(f)
	If file
		While Not Eof(file)
			l1$=ReadLine(file)
			l2$=ReadLine(file)
			l3$=ReadLine(file)
			l4$=ReadLine(file)
			l5$=ReadLine(file)
			
			paths1(l1,0)=CreateSphere(2);CreatePivot()
				ScaleMesh paths1(l1,0),.2,.2,.2
				EntityColor paths1(l1,0),0,150,0
				EntityFX paths1(l1,0),1
				;EntityAlpha paths1(l1,0),.5
				PositionEntity paths1(l1,0),l2,l3,l4
				EntityPickMode paths1(l1,0),2;???????????
				
			paths1b(l1)=l5
		Wend
	EndIf
End Function

Function SAVE_NODESFILE(f$)
	file=WriteFile(f)
	If file
		For p=0 To path_maxnodes ;999
			If paths1(p,0)>0
			WriteLine file,p
			WriteLine file,EntityX(paths1(p,0))
			WriteLine file,EntityY(paths1(p,0))
			WriteLine file,EntityZ(paths1(p,0))
			WriteLine file,paths1b(p)
			EndIf
		Next
	CloseFile file
	Delay 250
	EndIf
End Function

LOAD_NODESFILE("nodes.txt")

Function ADD_NODE(x#,y#,z#)
	For p=0 To path_maxnodes ;999
		If paths1(p,0)=0
		paths1(p,0)=CreateSphere(2) ;CreatePivot()
			ScaleMesh paths1(p,0),.2,.2,.2
			EntityColor paths1(p,0),0,150,0
			EntityFX paths1(p,0),1
			;EntityAlpha paths1(p,0),.5
			PositionEntity paths1(p,0),x,y,z
			EntityPickMode paths1(p,0),2 ;???????????
		Exit
		EndIf
	Next
End Function

Function GET_NEARNODE(ele)
	dist1#=100000
	num=-1
	For p=0 To path_maxnodes ;999
		If paths1(p,0)>0
		dist2#=EntityDistance(ele,paths1(p,0))
			If dist2<dist1
			dist1=dist2
			num=p
			EndIf
		EndIf
	Next
	Return num
End Function

Function FIND_PATH(from_node,to_node)

	If from_node+to_node>-1 And from_node<>to_node
	
	;-------------------------
	;--- Reset Path --------
	path_total=""
		For p=0 To path_maxnodes;999
		paths1(p,1)=0
		paths1(p,2)=0
		paths1(p,3)=0
		paths1(p,4)=0
		paths1(p,5)=0
		Next
		
		For amark.paths_marks=Each paths_marks
		FreeEntity amark\ele
		Delete amark
		Next
	
	;-------------------------

	dist#=0
	
	;If parent=-1 Then parent=from_node
	parent=from_node
	
.path_again

	nodes_in_list=False

	;For p=0 To path_maxnodes;999
	;	If p=parent ;If exists a node
		;nodes$=paths1b(p)
		nodes$=paths1b(parent)

			For l=1 To Len(nodes)/2
			num=Int(Mid(nodes,l*2-1,2))
				If paths1(num,1)=0 ;if in Default
				nodes_in_list=True
				
				paths1(num,1)=1 ;add node to Open list
				paths1(num,5)=parent ;-> set node parent
	
				;Calc G:
				dist=paths1(parent,3)+Int(EntityDistance(paths1(parent,0),paths1(num,0))*10)
				paths1(num,3)=dist
				;Calc H:
				;dist=EntityDistance(paths1(num,0),paths1(to_node,0))*10
				h=Abs(EntityX(paths1(num,0))-EntityX(paths1(to_node,0)))*10
				paths1(num,4)=h
				h=Abs(EntityY(paths1(num,0))-EntityY(paths1(to_node,0)))*10
				paths1(num,4)=paths1(num,4)+h
				h=Abs(EntityZ(paths1(num,0))-EntityZ(paths1(to_node,0)))*10
				paths1(num,4)=paths1(num,4)+h
				;Calc F: (G+H)
				paths1(num,2)=paths1(num,3)+paths1(num,4)
				
				ElseIf paths1(num,1)=1 ;if in Open list
					nodes_in_list=True
					
					For l2=1 To Len(paths1b(num))/2
					num2=Int(Mid(paths1b(num),l2*2-1,2))
						If paths1(num2,1)=2;if it is a parent
						checkg=paths1(num2,3)+Int(EntityDistance(paths1(num2,0),paths1(num,0))*10)
							If checkg<paths1(num,3)
							paths1(num,3)=checkg
							paths1(num,2)=paths1(num,3)+paths1(num,4)
							paths1(num,5)=num2;-> set new parent
							EndIf
						EndIf
					Next
				EndIf
			Next

		paths1(parent,1)=2;add parent to Closed list

		;Exit
		;EndIf
		
	;Next
	;Stop
	;Find lowest F and repeat the process:
	dist=100000
		For p=0 To path_maxnodes;999
			If paths1(p,0)>0
				If paths1(p,1)=1 ;if in Open list
					If paths1(p,2)<dist
						If nodes_in_list=False
						dist=paths1(p,2)
						newparent=p
						
						Else
							;For l=1 To Len(paths1b(parent))/2
							;s$=Mid(paths1b(parent),l*2-1,2)
							;	If Int(s)=p
								dist=paths1(p,2)
								newparent=p
							;	Exit
							;	EndIf
							;Next
						EndIf
					EndIf
				EndIf
			EndIf
		Next

		If parent=newparent ;-> indica que no hay solucion
		Goto path_false
		Else
		parent=newparent
		EndIf
	
		If parent=to_node
			If to_node=0
			path_total="00"
			ElseIf to_node<10
				path_total="0"+Str(to_node)
			Else
			path_total=Str(to_node)
			EndIf
			
			If Len(paths1b(from_node))>0
	
				Repeat
					newparent=paths1(parent,5)
					If newparent=0
					path_total=path_total+"00"
					ElseIf newparent<10
						path_total=path_total+"0"+Str(newparent)
					Else
					path_total=path_total+Str(newparent)
					EndIf
					parent=paths1(parent,5)
				Until newparent=from_node
				
			EndIf
	
		Else
		Goto path_again
		EndIf
.path_false
	;-----------------------------------------
	EndIf
End Function

Function CREATE_PATH()

	;--------------------
	;ADD a NODE
	If KeyHit(49) ;N
	ADD_NODE(EntityX(cam_player),EntityY(cam_player),EntityZ(cam_player))
	EndIf

	;--------------
	;Pick a Node:
	If MouseHit(1)
	path_picked=CameraPick(cam_player,GraphicsWidth()/2,GraphicsHeight()/2)
	EndIf	
	
	;----------------------------
	;----- MOVE A NODE ------
	If KeyDown(29);Left Ctrl
		If path_picked>0
			;Trasladar NODE
			If KeyDown(23); i - Forward
			TranslateEntity paths1(path_nodeselected,0),0,0,.05
			
			ElseIf KeyDown(37); K - Backward
				TranslateEntity paths1(path_nodeselected,0),0,0,-.05
			
			ElseIf KeyDown(36); J - Left
				TranslateEntity paths1(path_nodeselected,0),-.05,0,0
			
			ElseIf KeyDown(38); L - Right
				TranslateEntity paths1(path_nodeselected,0),.05,0,0
				
			ElseIf KeyDown(22) ;U - Up
				TranslateEntity paths1(path_nodeselected,0),0,.05,0
	
			ElseIf KeyDown(24) ;O - Down
				TranslateEntity paths1(path_nodeselected,0),0,-.05,0
			EndIf
		EndIf
	EndIf
	;----------------------------

	;-------------------------------------------
	;Asociate a NODE with the selected NODE
	If KeyHit(46) ;key C
		If path_picked>0
			For p=0 To path_maxnodes ;999
				If path_picked=paths1(p,0)
	
				SetBuffer FrontBuffer()
				Color 0,0,0
				Rect 20,25,GraphicsWidth(),30
				Color 255,255,255
				Locate 30,30
				FlushKeys
				s$=Input("NODE number to connect: "+paths1b(p))
				FlushKeys
					If Len(s)>0
					paths1b(p)=paths1b(p)+s
		
						If p=0
						s2$="00"
						ElseIf p<10
						s2$="0"+Str(p)
						Else
						s2$=p
						EndIf
					paths1b(s)=paths1b(s)+s2
					EndIf
	
				SetBuffer BackBuffer()
				Exit
				EndIf
			Next
		EndIf
	EndIf
	
	;---------------------------------------------------------
	;------- DELETE A CONNECTION with a NODE ---------
	If KeyHit(45) ;X
		If path_picked>0
			For p=0 To path_maxnodes ;999
				If path_picked=paths1(p,0)
	
				SetBuffer FrontBuffer()
				Color 0,0,0
				Rect 20,25,GraphicsWidth(),30
				Color 255,255,255
				Locate 30,30
				FlushKeys
				s$=Input("Delete Connection with NODE: ")
				FlushKeys
					If Len(s)>0
						For l=1 To Len(paths1b(p))/2
						s2$=Mid(paths1b(p),l*2-1,2)
							If s2=s
							paths1b(p)=Left(paths1b(p),Instr(paths1b(p),s2)-1)+Mid(paths1b(p),Instr(paths1b(p),s2)+2)
							Exit
							EndIf
						Next
						For l=1 To Len(paths1b(s))/2
						s2$=Mid(paths1b(s),l*2-1,2)
						p2=s2
							If p2=p
							paths1b(s)=Left(paths1b(s),Instr(paths1b(s),s2)-1)+Mid(paths1b(s),Instr(paths1b(s),s2)+2)
							Exit
							EndIf
						Next
					EndIf
	
				SetBuffer BackBuffer()
				Exit
				EndIf
			Next
		EndIf
	EndIf
	
	;-------------------------------------------
	;---- DELETE A NODE FROM SCENE ------
	If KeyHit(32) ;key D 
		If path_picked>0
			For p=0 To path_maxnodes ;999
				If path_picked=paths1(p,0)
				FreeEntity paths1(p,0)
				paths1(p,0)=0
				paths1(p,1)=0
				paths1(p,2)=0
				paths1(p,3)=0
				paths1(p,4)=0
				paths1(p,5)=0
				paths1b(p)=""
					For p2=0 To path_maxnodes ;999
					s$=paths1b(p2)
						If Len(s)>0
							If p=0
							checks$="00"
							ElseIf p<10
							checks$="0"+Str(p)
							Else
							checks$=Str(p)
							EndIf
							s2=""
							For l=1 To Len(s)/2
								s3$= Mid(s,l*2-1,2)
								If Not s3=checks
								s2=s2+s3
								EndIf
							Next
						paths1b(p2)=s2
						EndIf
					Next
				Exit
				EndIf
			Next
		EndIf
	EndIf

	;-------
	;Reset
	If KeyHit(57) ;SPACE
	path_total=""
	;enem_path=""
	parent=-1
		For p=0 To path_maxnodes ;999
		paths1(p,1)=0
		paths1(p,2)=0
		paths1(p,3)=0
		paths1(p,4)=0
		paths1(p,5)=0
		Next
		
		For amark.paths_marks=Each paths_marks
		FreeEntity amark\ele
		Delete amark
		Next
	reset=True
	EndIf
	
	;----------------------------------------------------
	;Change de Nodes From/To for the Pathfinding:
	If KeyHit(25) ;P
	SetBuffer FrontBuffer()
	Color 0,0,0
	Rect 20,25,GraphicsWidth(),40
	Color 255,255,255
	Locate 30,30
	FlushKeys
	Print "Enter two digits per node, eg: 37-00 (means the path will be found from node 37 to node 0)
	Locate 30,45
	s$=Input("Enter new NODES:  ")
	FlushKeys
		If Len(s)>0
		node1=Int(Left(s,2))
		node2=Int(Right(s,2))
		EndIf

	SetBuffer BackBuffer()
	EndIf
	
	;-------------------------------------------
	;---- SAVE NODES & CONNECTIONS ----
	If KeyHit(60) ;F2
	SAVE_NODESFILE("nodes.txt")
	EndIf
	;----------------------------------------

	;---------
	;Help
	If KeyHit(59) ;F1
	FlushKeys
	SetBuffer FrontBuffer()
	Color 0,0,0
	Rect 0,0,GraphicsWidth(),350
	Color 255,255,255
	Print:Print
	Print "     -Important:"
	Print "     -When you enter a node number anywhere in the editor you will have to do it with two digits."
	Print "     For example: if you want to point to the node number 5, you will write 05, if you"
	Print "     want the node 0, you write 00, if your node number is bigger than 9 then write it normally."
	Print:Print
	Print "     Cursors + Mouse  ------> Move"
	Print
	Print "     Key N                     -----> add a node at the camera position"
	Print "     Key D                     -----> delete selected node"
	Print "     key LMB                -----> pick a node"
	Print "     key C                     -----> enter a node number to connect the selected node to"
	Print "     key P                     -----> enter new "+Chr(34)+"from node"+Chr(34)+" -> "+Chr(34)+"to node"+Chr(34)+" numbers to use in the pathfinding"
	Print "     CTRL+[I,K,J,L,U,O] --> translate selected node"
	Print "     key X                     -----> delete a connection with a node"
	Print
	Print "     key ENTER            -----> Find path"
	Print "     Key SPACE           -----> Reset pathfinding"
	Print
	Print "     F2                           -----> Save Nodes+Connections to a .txt file>"
	Print "     key M                    -----> Load a new Mesh (you must write the path to the mesh, eg: 3dmodel/mylevel.3ds)"
	WaitKey()
	FlushKeys
	SetBuffer BackBuffer()
	EndIf
	
	;--------------
	;Load a Mesh
	If KeyHit(50);M
	FlushKeys
	SetBuffer FrontBuffer()
	Color 0,0,0
	Rect 0,0,500,350
	Color 255,255,255
	Print:Print
	s$=Input("     Load new mesh, write path: ")
		If Len(s)>0
			If m Then FreeEntity m
		m=LoadMesh(s)
		EndIf
	FlushKeys
	SetBuffer BackBuffer()
	EndIf
	
End Function

Function SHOW_NODES_STATS()
	;EntityColor the Nodes, draw numbers, and draw connection lines:
	For p=0 To path_maxnodes ;999
		If paths1(p,0)>0
		EntityColor paths1(p,0),0,150,0
		
		CameraProject cam_player,EntityX(paths1(p,0)),EntityY(paths1(p,0)),EntityZ(paths1(p,0))
		x1#=ProjectedX()
		y1#=ProjectedY()
		z1#=ProjectedZ()
		
			If z1>0
			Color 255,255,255
			Text x1,y1,p
				If EntityDistance(paths1(p,0),cam_player)<10
				Text x1,y1+10,"F: "+paths1(p,2)
				Text x1,y1+20,"G: "+paths1(p,3)
				Text x1,y1+30,"H: "+paths1(p,4)
				Text x1,y1+40,"Parent: "+paths1(p,5)
				Text x1,y1+50,"OnList: "+paths1(p,1)
				EndIf
			EndIf
			
			If path_picked>0
				If path_picked=paths1(p,0)
				EntityColor paths1(p,0),255,100,0
				path_nodeselected=p
				EndIf
			Else
			path_nodeselected=-1
			EndIf
			
			If paths1(p,1)=1
			EntityColor paths1(p,0),0,255,255
			EndIf
			If paths1(p,1)=2
			EntityColor paths1(p,0),255,0,0
			EndIf
			
			;Draw lines:
			Color 0,255,0
			If Len(paths1b(p))>0
			s$=paths1b(p)
				For l=1 To Len(s)/2
				num$=Mid(s,l*2-1,2)

				CameraProject cam_player,EntityX(paths1(num,0)),EntityY(paths1(num,0)),EntityZ(paths1(num,0))
				x2#=ProjectedX()
				y2#=ProjectedY()
				z2#=ProjectedZ()
					If z1>0 And z2>0
					Line x1,y1,x2,y2
					EndIf
				Next
			EndIf

			Color 255,255,255
			If path_picked=paths1(p,0)
			printnodes$=""
			s=paths1b(p)
				For l=1 To Len(s)/2
				printnodes=printnodes+Mid(s,l*2-1,2)+"-"
				Next
			Text 10,80,printnodes
			EndIf
		EndIf
	Next
	;------------------------------------
End Function

;***************************************

;Red cubes to show the found path:
Type paths_marks
	Field ele
End Type

Function ADD_MARKER(node1,node2)
	node1=paths1(node1,0)
	node2=paths1(node2,0)
	
	amark.paths_marks=New paths_marks
		amark\ele=CreateCube()
			EntityColor amark\ele,255,0,0
			EntityFX amark\ele,1
			PositionMesh amark\ele,0,0,1
			ScaleMesh amark\ele,.1,.1,1
			PositionEntity amark\ele,EntityX(node1),EntityY(node1),EntityZ(node1)
			PointEntity amark\ele,node2
			ScaleEntity amark\ele,1,1,interpolate(EntityDistance(amark\ele,node2),2,4,1,2)
End Function


While Not KeyDown(1)


	If KeyDown(200) MoveEntity cam_player,0,0,.2
	If KeyDown(208) MoveEntity cam_player,0,0,-.2
	If KeyDown(203) MoveEntity cam_player,-.2,0,0
	If KeyDown(205) MoveEntity cam_player,.2,0,0
	TurnEntity cam_player,MouseYSpeed()/12.0,-MouseXSpeed()/12.0,0
	RotateEntity cam_player,EntityPitch(cam_player),EntityYaw(cam_player),0
	MoveMouse GraphicsWidth()/2,GraphicsHeight()/2


	;--------------
	
	
	If KeyHit(28)
	parent=-1
	reset=True

		FIND_PATH(node1,node2)
		
	
	EndIf




	UpdateWorld
	


	;----------------
	
	RenderWorld
	

	;--------------------------------------------------
	;-------------- NODES EDITING -----------------
	If KeyHit(82) ;Numpad 0
	path_editing=Not path_editing
		If path_editing=1
		FlushMouse:FlushKeys
			For p=0 To path_maxnodes;999
				If paths1(p,0)>0
				ShowEntity paths1(p,0)
				EndIf
			Next
		Else
			For p=0 To path_maxnodes;999
				If paths1(p,0)>0
				HideEntity paths1(p,0)
				EndIf
			Next
		EndIf
	EndIf
	
	If path_editing
	CREATE_PATH()

	SHOW_NODES_STATS()
	
		;SHOW THE PATH
		If reset=True
			If Len(path_total)>0
			reset=False
				For l=1 To Len(path_total)/2
				s1$=Mid(path_total,l*2-1,2)
				s2$=Mid(path_total,l*2-1+2,2)
					If Len(s1)>0 And Len(s2)>0
					ADD_MARKER(s1,s2)
					EndIf
				Next
			EndIf
		EndIf
	Text GraphicsWidth()/2,5,"NODES >ED<",1
	Else
		For amark.paths_marks=Each paths_marks
		FreeEntity amark\ele
		Delete amark
		Next
	EndIf
	;--------------------------------------------------
	;--------------------------------------------------
	
	Color 255,0,0
	Oval GraphicsWidth()/2-3,GraphicsHeight()/2-3,6,6,0

	Color 255,255,255
	Text 10,100,"Nearest node to camera: "+GET_NEARNODE(cam_player)
	Text 10,120,"Selected node: "+path_nodeselected
	Text 10,140,"path_total: "+path_total
	Text 10,160,"Path: from <"+node1+"> to <"+node2+">"
	Text 10,180,"Enem_Path: "+enem_path
	Text 10,200,"Finding: "+finding
	
	Text 10,5,"F1-Help   |   Use Numpad 0 to enable/disable NODES editing"
	Text 10,20,"polys: "+TrisRendered()
	
	If KeyHit(17) w=Not w WireFrame w
	Flip
Wend

MoveMouse 400,300:End