taichi-dev/taichi_three

read .obj file faces to taichi tensor to render

Zony-Zhao opened this issue · 3 comments

@ti.func
def glTri(A, B, C):
    l = ti.atomic_add(tris_len[None], 1)
    pos1[l] = A
    pos2[l] = B
    pos3[l] = C


path = 'test.obj'
vertices = []
faces = []

def readobj():
    with open(path, "r") as myfile:
        data = myfile.readlines()
        # cache vertices

        for line in data:
            if line.startswith('v '):
                splitted = line.split()
                vertex = [float(splitted[1]),
                          float(splitted[2]),
                          float(splitted[3])
                          ]
                vertices.append(vertex)

        # cache faces
        # DONT merge this 'for loop'
        # must initialize vertices for faces to work
        print('length', len(vertices))
        for line in data:
            # line looks like 'f 5/1/1 1/2/1 4/3/1'
            if line.startswith('f '):
                splitted = line.split()
                faceVertices = []

                for i in range(1, 4):
                    # splitted[i] should look like '5/1/1'
                    # for vertex/vertex UV coords/vertex Normal  (indexes number in the list)
                    # the index in 'f 5/1/1 1/2/1 4/3/1' STARTS AT 1 !!!
                    index = int((splitted[i].split('/'))[0]) - 1
                    print(index)
                    faceVertices.append(vertices[index])
                faces.append(faceVertices)


@ti.kernel
def init():
    for i in range(len(faces)):
        print(faces)
        # vertex=faces[i]
        # glTri(ts.vec3(vertex[0], vertex[1], vertex[2]))


readobj()
# print(faces)
init()

image

I have tried a lot of methods, but failed to read .obj file to a list obj and iterate it in taichi-kernel scope.

Generally, I read an obj file and store vertices in the faces( a python list object), which is all well. When I try to iterate it in taichi-kernel scope, it fails. The 'faces' list object can neither be use like 'for i in faces' nor 'faces[i]'. Even when I try to print it, error happens.

Should I use a taichi tensor to store faces? However, it seems impossible to read .obj in kernel.

test.zip
For you guys who want the test .obj and source file.
commit 1941110 is required.

Thank for purposing this! You're right, it's impossible to directly copy data from python scope to taichi tensor.
But we may first convert it into a numpy array, which taichi has control, then use tensor.from_numpy to copy the data.

It's working now!

import taichi as ti
import taichi_glsl as ts
import taichi_three as t3
import numpy as np


def readobj(path):
    vertices = []
    faces = []
    with open(path, "r") as myfile:
        data = myfile.readlines()
        # cache vertices

        for line in data:
            if line.startswith('v '):
                splitted = line.split()
                vertex = [float(splitted[1]),
                          float(splitted[2]),
                          float(splitted[3])
                          ]
                vertices.append(vertex)

        # cache faces
        # DONT merge this 'for loop'
        # must initialize vertices for faces to work
        print('length', len(vertices))
        for line in data:
            # line looks like 'f 5/1/1 1/2/1 4/3/1'
            if line.startswith('f '):
                splitted = line.split()
                faceVertices = []

                for i in range(1, 4):
                    # splitted[i] should look like '5/1/1'
                    # for vertex/vertex UV coords/vertex Normal  (indexes number in the list)
                    # the index in 'f 5/1/1 1/2/1 4/3/1' STARTS AT 1 !!!
                    index = int((splitted[i].split('/'))[0]) - 1
                    print(index)
                    faceVertices.append(vertices[index])
                faces.append(faceVertices)

        return np.array(faces)


model = readobj('examples/test.obj') / 2

N = model.shape[0]


ti.init(ti.cpu)

scene = t3.SceneGE()
pos1 = ti.Vector(3, ti.f32)
pos2 = ti.Vector(3, ti.f32)
pos3 = ti.Vector(3, ti.f32)
ti.root.dense(ti.i, N).place(pos1, pos2, pos3)


scene.add_triangle(pos1, pos2, pos3)
scene.set_light_dir([0.4, -1.5, -1.8])
pos1.from_numpy(model[:, 0])
pos2.from_numpy(model[:, 1])
pos3.from_numpy(model[:, 2])


gui = ti.GUI('Loading Model', scene.res)
while gui.running:
    gui.running = not gui.get_event(ti.GUI.ESCAPE)
    scene.camera.from_mouse(gui)
    scene.render()
    gui.set_image(scene.img)
    gui.show()

图片

image
Great!