You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Lua中读取并解析OBJ文件数据?

Lua 读取OBJ文件并解析顶点与面

以下是实现需求的Lua代码,直接处理OBJ文件的顶点(v行)和面(f行),支持f行的/分割格式:

1. 定义基础数据结构

用Lua table模拟Vector3和Polygon对象:

-- 模拟Vector3结构,存储x/y/z坐标
local function Vector3(x, y, z)
    return {x = tonumber(x), y = tonumber(y), z = tonumber(z)}
end

-- 模拟Polygon结构,存储组成面的Vector3列表
local function Polygon(vertices)
    return {vertices = vertices or {}}
end

2. 核心解析逻辑

local function parseObjFile(filePath)
    local vertices = {}  -- 存储所有顶点,索引从1开始(匹配OBJ的编号规则)
    local polygons = {}  -- 存储所有面

    -- 打开文件
    local file = io.open(filePath, "r")
    if not file then
        error("无法打开文件: " .. filePath)
    end

    -- 逐行读取处理
    for line in file:lines() do
        -- 去掉首尾空白
        line = line:gsub("^%s+", ""):gsub("%s+$", "")
        if line == "" then goto continue end  -- 跳过空行

        -- 拆分行为单词列表
        local words = {}
        for word in line:gmatch("%S+") do
            table.insert(words, word)
        end

        local firstWord = words[1]
        -- 处理顶点行(v开头)
        if firstWord == "v" then
            -- 提取x/y/z三个数值,创建Vector3存入vertices
            local vec = Vector3(words[2], words[3], words[4])
            table.insert(vertices, vec)
        -- 处理面行(f开头)
        elseif firstWord == "f" then
            local polyVertices = {}
            -- 遍历每个顶点引用(从第二个单词开始)
            for i = 2, #words do
                local vertexRef = words[i]
                -- 提取/分割前的顶点编号(OBJ编号从1开始)
                local vertexIndex = tonumber(vertexRef:match("^%d+"))
                -- 从vertices中取出对应的Vector3,加入当前面的顶点列表
                table.insert(polyVertices, vertices[vertexIndex])
            end
            -- 创建Polygon对象存入polygons
            table.insert(polygons, Polygon(polyVertices))
        end

        ::continue::
    end

    file:close()
    return vertices, polygons
end

3. 测试示例

假设你的OBJ文件内容如下:

v 4.0 7.0 5.0
v 1.0 5.0 1.0
v 5.0 4.0 2.0
v 6.0 1.0 7.0
f 1 4
f 3 2
f 1/1/1 2/4/1 4/9/1 3/7/1

调用解析函数并输出结果:

local vertices, polygons = parseObjFile("test.obj")

-- 打印所有顶点
print("顶点列表:")
for i, vec in ipairs(vertices) do
    print(string.format("Vector%d: (%.1f, %.1f, %.1f)", i, vec.x, vec.y, vec.z))
end

-- 打印所有面
print("\n面列表:")
for i, poly in ipairs(polygons) do
    io.write(string.format("第%d个面: ", i))
    for j, vec in ipairs(poly.vertices) do
        io.write(string.format("(%.1f,%.1f,%.1f) ", vec.x, vec.y, vec.z))
    end
    io.write("\n")
end

输出结果:

顶点列表:
Vector1: (4.0, 7.0, 5.0)
Vector2: (1.0, 5.0, 1.0)
Vector3: (5.0, 4.0, 2.0)
Vector4: (6.0, 1.0, 7.0)

面列表:
第1个面: (4.0,7.0,5.0) (6.0,1.0,7.0) 
第2个面: (5.0,4.0,2.0) (1.0,5.0,1.0) 
第3个面: (4.0,7.0,5.0) (1.0,5.0,1.0) (6.0,1.0,7.0) (5.0,4.0,2.0) 

关键细节说明

  • OBJ文件的顶点编号是1-based,所以我们直接用Lua数组的1索引存储,匹配编号规则。
  • 处理f行时,通过^%d+正则提取/之前的顶点编号,忽略纹理坐标、法向量等额外信息(如果需要这些信息,可以扩展正则匹配)。
  • 代码包含了空行跳过、文件打开失败的错误处理,保证基本鲁棒性。

内容的提问来源于stack exchange,提问作者TheJalfireKnight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:55:30