3D网格寻路实现 lua 代码

最近主要是有个很迫切需求要实现能在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/

搜索谷歌 "空间直线及其方程"

原文地址:https://www.cnblogs.com/maikkk/p/2523819.html