如何将 STL 导入 pygltflib [英] How do I import an STL into pygltflib

查看:17
本文介绍了如何将 STL 导入 pygltflib的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将 STL 文件作为网格导入 pygltflib?我试过 gltf = GLTF2().load(filename) 但它只接受有效的 gltf.

How do I import an STL file as a mesh into pygltflib? I have tried gltf = GLTF2().load(filename) but that only accepts a valid gltf.

推荐答案

我使用了 pygltflib 和 <一个 href="https://pypi.org/project/numpy-stl/" rel="nofollow noreferrer">numpy-stl 用于这个,它实际上并不难,因为 .stl 文件通常满足这些条件:

I used pygltflib and numpy-stl for this and it actually was not to hard, because .stl files typically meet these conditions:

  1. 仅由构成三角形的点/顶点的三元组组成
  2. 点的顺序无关紧要,而是存储面部法线
  3. STL 只包含一个对象
  4. 没有存储颜色或纹理,只有原始三角形网格

考虑到这些想法,我想出了一个非常基本的实现:

With these ideas in mind I came up with a very basic implementation:

import pygltflib
import numpy as np
from stl import mesh
from math import sqrt

def normalize(vector):
    norm = 0
    for i in range(0, len(vector)):
        norm += vector[i] * vector [i]
    norm = sqrt(norm)
    for i in range(0, len(vector)):
        vector[i] = vector[i] / norm

    return vector

stl_mesh = mesh.Mesh.from_file('cube.stl')

stl_points = []
for i in range(0, len(stl_mesh.points)): # Convert points into correct numpy array
    stl_points.append([stl_mesh.points[i][0],stl_mesh.points[i][1],stl_mesh.points[i][2]])
    stl_points.append([stl_mesh.points[i][3],stl_mesh.points[i][4],stl_mesh.points[i][5]])
    stl_points.append([stl_mesh.points[i][6],stl_mesh.points[i][7],stl_mesh.points[i][8]])

points = np.array(
    stl_points,
    dtype="float32",
)

stl_normals = []
for i in range(0, len(stl_mesh.normals)): # Convert points into correct numpy array
    normal_vector = [stl_mesh.normals[i][0],stl_mesh.normals[i][1],stl_mesh.normals[i][2]]
    normal_vector = normalize(normal_vector)
    stl_normals.append(normal_vector)
    stl_normals.append(normal_vector)
    stl_normals.append(normal_vector)

normals = np.array(
    stl_normals,
    dtype="float32"
)

points_binary_blob = points.tobytes()
normals_binary_blob = normals.tobytes()

gltf = pygltflib.GLTF2(
    scene=0,
    scenes=[pygltflib.Scene(nodes=[0])],
    nodes=[pygltflib.Node(mesh=0)],
    meshes=[
        pygltflib.Mesh(
            primitives=[
                pygltflib.Primitive(
                    attributes=pygltflib.Attributes(POSITION=0, NORMAL=1), indices=None
                )
            ]
        )
    ],
    accessors=[
        pygltflib.Accessor(
            bufferView=0,
            componentType=pygltflib.FLOAT,
            count=len(points),
            type=pygltflib.VEC3,
            max=points.max(axis=0).tolist(),
            min=points.min(axis=0).tolist(),
        ),
        pygltflib.Accessor(
            bufferView=1,
            componentType=pygltflib.FLOAT,
            count=len(normals),
            type=pygltflib.VEC3,
            max=None,
            min=None,
        ),
    ],
    bufferViews=[
        pygltflib.BufferView(
            buffer=0,
            byteOffset=0,
            byteLength=len(points_binary_blob),
            target=pygltflib.ARRAY_BUFFER,
        ),
        pygltflib.BufferView(
            buffer=0,
            byteOffset=len(points_binary_blob),
            byteLength=len(normals_binary_blob),
            target=pygltflib.ARRAY_BUFFER,
        ),
    ],
    buffers=[
        pygltflib.Buffer(
            byteLength=len(points_binary_blob) + len(normals_binary_blob)
        )
    ],
)
gltf.set_binary_blob(points_binary_blob + normals_binary_blob)
gltf.save("converted.glb")

我使用 OpenSCAD 中生成的 ASCII 编码 .stl 文件对此进行了测试,该文件可以在 这个要点.

I tested this with ASCII encoded .stl files generated in OpenSCAD, that can be found in this gist.

第一部分,是将 numpy-stl 的数组布局中的点和法线转换为 pygltflib 接受的数组类型.从那里开始,它只是使用 pygltflib 的基本工作,以构建相应的 .gltf 文件.

The first part, was converting the points and normals from numpy-stl's array layout, to the kind of array accepted by pygltflib. From there on it's just basic working with the pygltflib, to build the corresponding .gltf file.

代码目前有一个小问题.

The code has currently one small Issue.

  1. 模型旋转出来

解决这个问题应该很容易,您只需要将坐标变换应用到点和法线.但是因为模型可以在空间中自由旋转所以我没有费心去解决这个问题.

Fixing that should be easy, you would only have to apply a coordinate transformation to the points and normals. But because the model can be rotated in space freely nevertheless I did not bother to fix this.

还有一些限制,不容易克服.例如,如果您想为 .stl 的不同部分分配不同的材料,这是行不通的,因为实际上没有关于 part 是什么的信息.不过,仅对模型使用单一纹理/颜色很简单.

There are also some limitations, that could not easily be overcome. For example if you would like to assign different materials to different parts of the .stl this can not work, because there is quite literally no information about what a part is. Using only a single texture / color for the model is simple, though.

这篇关于如何将 STL 导入 pygltflib的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆