taichi-dev / meshtaichi

MeshTaichi: A Compiler for Efficient Mesh-based Operations (SIGGRAPH Asia 2022)
213 stars 11 forks source link

how to load custom mesh #6

Open StuvX opened 1 year ago

StuvX commented 1 year ago

Hi - how can I load my own mesh created in Rhino3d?

I've tried PLY, STL, and OBJ but have not been able to get it to work.

g1n0st commented 1 year ago

Hi StuvX,

The API used to load a mesh is load_mesh. You can see the detailed usage here: https://github.com/taichi-dev/meshtaichi/blob/d745ea728ce2e6a5f0faa304887b6616e6cec139/vertex_normal/normal.py#L13

Please post the related error message if you have trouble using the API. Please let me know if you need further support to get your application working! : )

StuvX commented 1 year ago

Thanks - but I still receive the following error:

Traceback (most recent call last): File "/taichi/massSpring.py", line 20, in mesh = Patcher.load_mesh(args.model, relations=["FV"]) File "/miniconda3/envs/taichi/lib/python3.10/site-packages/meshtaichi_patcher/init.py", line 32, in load_mesh return ti.Mesh._create_instance(mesh2meta(meshes, File "/miniconda3/envs/taichi/lib/python3.10/site-packages/meshtaichi_patcher/init.py", line 106, in mesh2meta m.patch(max_order, patch_relation) File "/miniconda3/envs/taichi/lib/python3.10/site-packages/meshtaichi_patcher/meshpatcher.py", line 63, in patch self.patcher.patch() IndexError: index 0 is out of bounds for axis 0 with size 0

g1n0st commented 1 year ago

It seems an internal error was generated by the patcher side. @BillXu2000 could you have a look?

BillXu2000 commented 1 year ago

Thanks - but I still receive the following error:

Traceback (most recent call last): File "/taichi/massSpring.py", line 20, in mesh = Patcher.load_mesh(args.model, relations=["FV"]) File "/miniconda3/envs/taichi/lib/python3.10/site-packages/meshtaichi_patcher/init.py", line 32, in load_mesh return ti.Mesh._create_instance(mesh2meta(meshes, File "/miniconda3/envs/taichi/lib/python3.10/site-packages/meshtaichi_patcher/init.py", line 106, in mesh2meta m.patch(max_order, patch_relation) File "/miniconda3/envs/taichi/lib/python3.10/site-packages/meshtaichi_patcher/meshpatcher.py", line 63, in patch self.patcher.patch() IndexError: index 0 is out of bounds for axis 0 with size 0

@StuvX Could you please give me this mesh file somehow? I will try to fix this bug on meshtaichi.

StuvX commented 1 year ago

@BillXu2000 You can use this code to generate the PLY file:

import numpy as np
import taichi as ti
import meshtaichi_patcher as Patcher

ti.init(arch=ti.cpu)

coords = [
    [1,0,0],
    [0,1,0],
    [1,1,0],
    [0,1,0],
    [1,1,1],
    [1,1,0],
    [1,1,1],
    [1,1,0],
    [1,0,0],
    [1,1,1],
    [0,1,0],
    [1,0,0]
    ]

faces = [
    [2,0,1],
    [5,3,4],
    [7,6,8],
    [10,11,9]
    ]

verts = np.array(coords, dtype=np.float32)
faces = np.array(faces, dtype=np.float32)

xs = verts[:,0]
ys = verts[:,1]
zs = verts[:,2]

meshOut = ti.tools.PLYWriter(len(xs), len(faces))
meshOut.add_vertex_pos(xs,ys,zs)
meshOut.add_faces(faces)
meshOut.export_ascii('tetra.ply')

meshIn = Patcher.load_mesh('tetra.ply')
LexTran commented 1 year ago

Hi, I've reached a similar problem, I was using meshio to save a mesh into PLY file and load it into meshtaichi, but I have failed, the error message is as follow:

[Taichi] version 1.4.1, llvm 15.0.1, commit e67c674e, win, python 3.10.9
Warning: cell_type "tetra" is not supported by PLY format - skipping
D:\Anaconda3\envs\taichi\lib\site-packages\meshio\ply\_ply.py:380: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of 
numpy, it will be understood as (type, (1,)) / '(1,)type'.
  [("count", count_dtype), ("data", data_dtype * cells_per_row)]
Traceback (most recent call last):
  File "E:\Work\mesh_demo.py", line 39, in <module>
    theMesh = Patcher.load_mesh("sphere.ply", relations=["FV"])
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshtaichi_patcher\__init__.py", line 32, in load_mesh
    return ti.Mesh._create_instance(mesh2meta(meshes, 
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshtaichi_patcher\__init__.py", line 100, in mesh2meta
    total = load_mesh_rawdata(total)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshtaichi_patcher\__init__.py", line 156, in load_mesh_rawdata
    m = meshio.read(filename)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\_helpers.py", line 71, in read
    return _read_file(Path(filename), file_format)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\_helpers.py", line 103, in _read_file
    return reader_map[file_format](str(path))
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\ply\_ply.py", line 61, in read
    mesh = read_buffer(f)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\ply\_ply.py", line 144, in read_buffer
    mesh = _read_binary(
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\ply\_ply.py", line 316, in _read_binary
    buffer_increment, cell_data[name] = _read_binary_list(
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\ply\_ply.py", line 384, in _read_binary_list
    cell_type = cell_type_from_count(cells.shape[1])
IndexError: tuple index out of range

This is how my code looks like:

import pygmsh
import meshio
import taichi as ti
import meshtaichi_patcher as Patcher
import numpy as np

with pygmsh.occ.Geometry() as geom:
    # Define an ellipsoid with semi-axes 1, 1, 1
    ellipsoid = geom.add_ellipsoid([0.0, 0.0, 0.0], [1.0, 1.0, 1.0])
    # Define a disk with radius 1 and center at origin
    disk = geom.add_disk([0.0, 0.0], 1.0)
    # Intersect the ellipsoid and the disk to get a spherical surface
    sphere = geom.boolean_intersection([ellipsoid], [disk])
    # Set the maximum characteristic length of the mesh to 0.1
    geom.characteristic_length_max = 0.1
    # Generate the mesh
    mesh = geom.generate_mesh()

# Write the mesh to a file using meshio
meshio.write("sphere.ply", mesh)

# Plot the mesh using taichi
# load the mesh, define the relations in advance, 
# F represents faces, E represents edges and V represents vertices
theMesh = Patcher.load_mesh("sphere.ply", relations=["FV"])
# define the x field, which is the position of each vertex
theMesh.verts.place({'x' : ti.math.vec3})
# transfer the data from numpy to taichi
theMesh.verts.x.from_numpy(theMesh.get_position_as_numpy())
# define a field to store the indices
display_indices = ti.field(ti.i32, shape = len(theMesh.faces) * 3)
# transfer the vertex indices of each face to the display_indices field
@ti.kernel
def init_surf_indices(mesh: ti.template(), indices: ti.template()):
    for f in mesh.faces:
        for j in ti.static(range(3)): # three vertices per face
            indices[f * 3 + j] = mesh.faces[f][j]

init_surf_indices(theMesh, display_indices)

window = ti.ui.Window("taichimesh", (1024, 1024))
canvas = window.get_canvas()
scene = ti.ui.Scene()
camera = ti.ui.Camera()
camera.up(0, 1, 0)
camera.fov(75)
camera.position(4.5,4.5,0.6)
camera.lookat(3.8, 3.8, 0.5)
camera.fov(75)

frame = 0
paused = ti.field(int, shape=())
paused[None] = 1
while window.running:
    for e in window.get_events(ti.ui.PRESS):
        if e.key == ti.ui.SPACE:
            paused[None] = not paused[None]
            print("paused:", paused[None])
    if not paused[None]:
        # substep()
        print(f"frame: {frame}")
        frame += 1
    # print("camera.curr_position",camera.curr_position)
    # print("camera.curr_lookat",camera.curr_lookat)

    # wasdqe can move the camera
    camera.track_user_inputs(window, movement_speed=0.05, hold_key=ti.ui.RMB)
    scene.set_camera(camera)

    # render the mesh
    scene.mesh(theMesh.verts.x, display_indices, color = (0.5,0.5,0.5))

    scene.particles(theMesh.verts.x, radius=1e-2, color = (1,0.5,0.5))

    scene.point_light(pos=(0.5, 1.5, 0.5), color=(1, 1, 1))
    scene.ambient_light((0.5,0.5,0.5))

    canvas.scene(scene)

    window.show()

As you can see, I was using pygmsh to generate a simple ellipsoid, but I can't load it through Patcher.load_mesh, I don't know where's the problem. Also, I was wondering if there is a way to generate mesh through meshtaichi directly? So I don't have to save it as PLY and then load it, which is kind of silly.

LexTran commented 1 year ago

I have tried to load an obj file generated by blender, and I got another error like follow:

[Taichi] version 1.4.1, llvm 15.0.1, commit e67c674e, win, python 3.10.9
[Taichi] Starting on arch=x64
Traceback (most recent call last):
  File "E:\Work\WEB_mesh.py", line 8, in <module>
    theMesh = Patcher.load_mesh("WEB1.obj", relations=["FV"])
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshtaichi_patcher\__init__.py", line 32, in load_mesh
    return ti.Mesh._create_instance(mesh2meta(meshes,
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshtaichi_patcher\__init__.py", line 100, in mesh2meta
    total = load_mesh_rawdata(total)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshtaichi_patcher\__init__.py", line 156, in load_mesh_rawdata
    m = meshio.read(filename)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\_helpers.py", line 71, in read
    return _read_file(Path(filename), file_format)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\_helpers.py", line 103, in _read_file
    return reader_map[file_format](str(path))
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\obj\_obj.py", line 18, in read
    mesh = read_buffer(f)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\obj\_obj.py", line 98, in read_buffer
    return Mesh(points, cells, point_data=point_data, cell_data=cell_data)
  File "D:\Anaconda3\envs\taichi\lib\site-packages\meshio\_mesh.py", line 166, in __init__
    raise ValueError(
ValueError: len(points) = 7556, but len(point_data["obj:vt"]) = 7668
dipanjan92 commented 9 months ago

@LexTran I also encountered the same error. The OBJ file I was trying to load had index starting from 1. If you used tools like Matlab to generate your OBJ files then most likely the index starts from 1 rather than 0 as MeshTaichi expects it to be. One quick fix I did is first loading the OBJ using Trimesh and then exporting the loaded mesh back to OBJ/PLY file. This worked in my case.