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

查看:105
本文介绍了如何将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天全站免登陆