@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.
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