最近主要是有个很迫切需求要实现能在3D网格里面实现自动寻路
其实之前一直思考如何去实现,也找了不少资料和代码,最近脑海里面才形成比较完整思路
首先要知道地图网格数据,里面包含了顶点坐标和三角形面
把地图网格数据可以转成成ply文件格式,用meshlab打开
ply
format ascii 1.0
comment VCGLIB generated
element vertex (顶多数量)
property float x
property float y
property float z
element face (三角形面的数量)
property list uchar int vertex_indices
end_header
(顶多坐标定义)
(三角形面定义)
通过上面的截图看到,地图是通过三角形面进行连接的
那么我们要实现寻路,就必须要知道开始和结束坐标轴三角形哪个面
然后再根据网格直接关系进行遍历,其实是一个图的遍历算法来实现
下面是遍历查找三角形面序号的lua代码
function getnextmeshtris(ss,d,mesh) local retTrisList = {} if mesh.tris[ss].visit ~= nil and mesh.tris[ss].visit == true then return retTrisList end mesh.tris[ss].visit = true print("getnextmeshtris next="..ss) local sstr = "" for k,v in pairs(mesh.tris[ss]) do if type(v) == "table" then sstr = sstr .. k.."={" for _,vv in pairs(v) do sstr = sstr ..vv.."," end sstr = sstr.."}," elseif type(v) == "number" or type(v) == "string" then sstr = sstr .. k.."="..v.."," end end print(sstr) local findend = false for k,v in pairs(mesh.tris[ss]) do if not findend and string.find(k,"connect") ~= nil then for _,c in pairs(v) do if c == d then print("getnextmeshtris in findend") table.insert(retTrisList,d) findend = true else print("getnextmeshtris next next"..c + 1) local l = getnextmeshtris(c + 1,d,mesh) for kk,vv in pairs(l) do print("getnextmeshtris insert "..vv) table.insert(retTrisList,vv) end if table.getn(l) > 0 then table.insert(retTrisList,ss) end end end end end print("getnextmeshtris next return") return retTrisList end -- 得到三角形的连接面 function get_tris_connect_in_mesh(s,d,mesh) local retTrisIndexList = {} local sstr = "" for k,v in pairs(mesh.tris[s]) do if type(v) == "table" then sstr = sstr .. k.."={" for _,vv in pairs(v) do sstr = sstr ..vv.."," end sstr = sstr.."}," else sstr = sstr .. k.."="..v.."," end end print(sstr) sstr = "" for k,v in pairs(mesh.tris[s]) do if string.find(k,"tartVert") ~= nil then sstr = sstr..k.."=[".."x="..mesh.verts[v + 1].x..",y="..mesh.verts[v + 1].y..",z="..mesh.verts[v + 1].z.."]," end end print(sstr) sstr = "" for k,v in pairs(mesh.tris[d]) do if type(v) == "table" then sstr = sstr .. k.."={" for _,vv in pairs(v) do sstr = sstr ..vv.."," end sstr = sstr.."}," else sstr = sstr .. k.."="..v.."," end end print(sstr) sstr = "" for k,v in pairs(mesh.tris[d]) do if string.find(k,"tartVert") ~= nil then sstr = sstr..k.."=[".."x="..mesh.verts[v + 1].x..",y="..mesh.verts[v + 1].y..",z="..mesh.verts[v + 1].z.."]," end end print(sstr) local findend = false mesh.tris[s].visit = true for k,v in pairs(mesh.tris[s]) do if not findend and string.find(k,"connect") ~= nil then for _,c in pairs(v) do if c == d then print("get_tris_connect_in_mesh once") table.insert(retTrisIndexList,s) table.insert(retTrisIndexList,d) findend = true else print("getnextmeshtris next start:"..c + 1) local l = getnextmeshtris(c + 1,d,mesh) for kk,vv in pairs(l) do print("get_tris_connect_in_mesh insert "..vv) table.insert(retTrisIndexList,vv) end if table.getn(l) > 0 then table.insert(retTrisIndexList,s) else print("getnextmeshtris return nil ") end mesh.tris[s].visit = true end end end end for kkk,vvv in pairs(retTrisIndexList) do print(vvv) end print("get_tris_connect_in_mesh end") return retTrisIndexList end
下面是求点到空间直线的垂线交点函数
-- 求点到空间直线的交点 function GetPointCoressLine(point,linepoints) -- 两点直线的空间向量 local xline = {x=linepoints[1].x - linepoints[2].x,y=linepoints[1].y - linepoints[2].y,z=linepoints[1].z - linepoints[2].z} -- 直线方程 --local t = (x -linepoints[2].x)/xline.x = (y -linepoints[2].y)/xline.y = (z -linepoints[2].z)/xline.z -- 求过point 垂直直线的平面方程 --xline.x * (x - point.x) + xline.y * (y - point.y) + xline.z * (z - point.z) = 0 --把 直线方程和平面方程带入求出t --local x = t * xline.x + linepoints[2].x --local y = t * xline.y + linepoints[2].y --local z = t * xline.z + linepoints[2].z --xline.x * (t * xline.x + linepoints[2].x - point.x) + xline.y * (t * xline.y + linepoints[2].y - point.y) + xline.z * (t * xline.z + linepoints[2].z - point.z) = 0 local t = -(xline.x * (linepoints[2].x - point.x) + xline.y * (linepoints[2].y - point.y) + xline.z * (linepoints[2].z - point.z))/(xline.x * xline.x + xline.y * xline.y + xline.z * xline.z) local x = t * xline.x + linepoints[2].x local y = t * xline.y + linepoints[2].y local z = t * xline.z + linepoints[2].z print(x..","..y..","..z) return {x,y,z} end
下面是计算一个空间坐标点在哪个三角形面上(代码中家里....)
参考资料
http://course.zjnu.cn/wyh/show.asp?id=185
http://61.139.105.132/gdsx/dzja/6/5.htm
http://www.pathengine.com/index.php
http://www.pathengine.com/downloads.php
https://code.google.com/p/critterai/
搜索谷歌 "空间直线及其方程"