tak0kadaの何でもノート

発声練習、生存確認用。

医学関連は 医学ノート

vispyで.objファイルをプロットする

OpenGLを使わずに.obj形式のメッシュの可視化を自由にしたい。vispyを試してみたところ、簡単だがOpenGLなしでは自由な表現が出来なかった。開発中で実装が充実している最中なので今後もっと使いやすくなるかも。以下メモ。

インストール

過不足があるかもしれない。condaでインストールすることが推奨されているが使いたくなかった。

sudo apt install python3-pyqt5 python3-pyside python3-pyqt5.opengl python3-pyqt5.qtopengl python3-QtOpenGL python3-pyqt4.qtopengl python3-pyglet

git clone https://github.com/vispy/vispy.git && cd vispy
sudo python3 setup.py install

ドキュメント

Documentation — VisPy

スクリプト

vispy.use()で使用するライブラリを選択できる。今回はPyQt4が一番安定していたので選択した。

import numpy as np
import vispy
from vispy import scene
from vispy.scene.visuals import Markers
from vispy.geometry import MeshData
from vispy.color import Color
import sys

#========== IO ==========
# read .obj file
with open("bunny.obj", 'r') as f:
    obj = f.readlines()
    vertices_loc = [[float(x) for x in line[2:].strip('\n').split(' ')]\
        for line in obj if line[0] == 'v']
    vertices_loc = np.array(vertices_loc)
    
    faces_id = [[int(v)-1 for v in line[2:].strip('\n').split(' ')]\
         for line in obj if line[0] == 'f']
    faces_id = np.array(faces_id)

nF = len(faces_id)
nV = len(vertices_loc)

# read data
with open("rho.txt", 'r') as f:
    rho = f.readlines()
    rho = np.array([float(line.strip('\n')) for line in rho])


#========== MESH CREATION =========
# create mesh
mesh = MeshData(vertices_loc, faces_id)

#face_color = np.array([[1, 0.5, 0, 1] for i in range(nF)])
face_color = np.array([[1, 1, 1, 0.9] for i in range(nF)])
mesh.set_face_colors(face_color)

#========== VERTICES ==========
# convex(凸):red, concave(凹): green
# normalize color
if rho.max() == rho.min():
    vertex_color = np.array([[0.5, 0.5, 0, 1] for i in range(nV)])
else:
    if len(rho) != nV:
        print("false")
    rho = (rho - rho.min()) / (rho.max() - rho.min())
    # just for now
    rho = rho[:nV]
    vertex_color = np.array([[i, 1 - i, 0, 1] for i in rho])

vertices = Markers()
vertices.set_data(vertices_loc, edge_color=None, face_color=vertex_color, size=10)


#========== VISUALIZATION ==========
vispy.use("PyQt4")

canvas = scene.SceneCanvas(keys = "interactive", size=(800, 800), show=True)
view = canvas.central_widget.add_view()
mesh = scene.visuals.Mesh(meshdata=mesh, shading="flat")
#mesh = scene.visuals.Mesh(meshdata=mesh, shading="smooth")
view.add(mesh)
view.add(vertices)
view.bgcolor = "grey"
view.camera = "turntable"
view.padding = 100
canvas.show()


if __name__ == "__main__":
    if sys.flags.interactive != 1:
        canvas.app.run()

拡大してもそれなりに見える。ただ今のところvispy.geometry.MeshDataはエッジの太さや色、頂点の塗り方をあまりいじれない。これは面だけに色をつけている。

頂点上の値をvispy.scene.visuals.Markersでプロットしようとしたもの。頂点のうち一部しかプロットされず失敗。

追記

MeshLabというものがあるらしい。

MeshLabを使ったメッシュのプレビュー | 研究開発日誌