owl-project / NVISII

Apache License 2.0
327 stars 28 forks source link

Cannot load GLB files using `nvisii.import_scene` #112

Open TontonTremblay opened 3 years ago

TontonTremblay commented 3 years ago

When loading a GLB file from amazon-berkeley 3d models I get this error:

Found 1 GPUs available for rendering.
Importing B016ID2V5O.glb...
Creating material B016ID2V5O_MAT_MR
    Detected attached DIFFUSE texture - /*0
    Detected attached NORMALS texture - /*2
Creating material 
Loading texture /*0
Warning: unable to load texture /*0 : basic_string::_S_construct null not valid
Loading texture /*2
Warning: unable to load texture /*2 : basic_string::_S_construct null not valid
Creating material : B016ID2V5O_MAT_MR
Assigning base color : 1 1 1
Segmentation fault (core dumped)

One way around this if you want to load the object is to load the raw data using a third party python loader.

def load_amazon_berkeley_object(path,suffix = ""):
    """
        This loads a single entity from a glb file. Assume the scene is one object. 

        path: path to the glb file 
        suffix: string to add to the name
        return: a visii entity
    """
    import trimesh
    scene = trimesh.load(path)

    for node in scene.graph.nodes_geometry:
        transform, node_name = scene.graph[node]

        mesh_tri = scene.geometry[node_name]

        points = np.array(mesh_tri.vertices)
        normals = np.array(mesh_tri.vertex_normals)
        triangles = np.array(mesh_tri.faces)
        # Flip the uvs
        uvs = np.array(mesh_tri.visual.uv)
        uvs[:,1] = 1-uvs[:,1]

        # get the textures
        tex_color_raw = np.array(mesh_tri.visual.material.baseColorTexture)
        tex_metallic_roughness = np.array(mesh_tri.visual.material.metallicRoughnessTexture)
        tex_normal = np.array(mesh_tri.visual.material.normalTexture)

        node_name = node_name + suffix

        mesh_visii = visii.mesh.create_from_data(
                        name = node_name,
                        positions = points.flatten(),
                        normals = normals.flatten(), 
                        texcoords = uvs.flatten(),
                        indices = triangles.flatten()
                    )

        ones = np.ones((tex_color_raw.shape[0],tex_color_raw.shape[1],1))

        material = visii.material.create(node_name)

        if tex_color_raw.shape[-1]==3:
            tex_color_raw = np.concatenate([tex_color_raw,ones],axis = 2)

        tex_color = visii.texture.create_from_data(
            node_name + 'color',
            tex_color_raw.shape[0],
            tex_color_raw.shape[1],
            (tex_color_raw.flatten()/255.0).astype(np.float32)
        )

        tex_roughness = visii.texture.create_from_data(
            node_name + 'roughness',
            tex_metallic_roughness.shape[0],
            tex_metallic_roughness.shape[1],
            (np.concatenate(
                [
                    np.expand_dims(tex_metallic_roughness[:,:,1],axis=-1),
                    np.expand_dims(tex_metallic_roughness[:,:,1],axis=-1),
                    np.expand_dims(tex_metallic_roughness[:,:,1],axis=-1),
                    np.ones((tex_color_raw.shape[0],tex_color_raw.shape[1],1))
                ],axis=2
            ).flatten()/255.0).astype(np.float32),
            linear = True
        )

        tex_metallic = visii.texture.create_from_data(
            node_name + 'metallic',
            tex_color_raw.shape[0],
            tex_color_raw.shape[1],
            (np.concatenate(
                [
                    np.expand_dims(tex_metallic_roughness[:,:,0],axis=-1),
                    np.expand_dims(tex_metallic_roughness[:,:,0],axis=-1),
                    np.expand_dims(tex_metallic_roughness[:,:,0],axis=-1),
                    np.ones((tex_color_raw.shape[0],tex_color_raw.shape[1],1))
                ],axis=2
            ).flatten()/255.0).astype(np.float32),
            linear = True
        )
        if len(tex_normal.shape)>2:
            tex_normal = visii.texture.create_from_data(
                node_name + 'normal',
                tex_normal.shape[0],
                tex_normal.shape[1],
                (np.concatenate([tex_normal,ones],axis = 2).flatten()/255.0).astype(np.float32),
                linear=True
            )
            material.set_normal_map_texture(tex_normal)

        material.set_base_color_texture(tex_color)
        material.set_metallic_texture(tex_metallic)
        material.set_roughness_texture(tex_roughness)

        entity_obj = visii.entity.create(
                        name = node_name,
                        transform = visii.transform.create(node_name),
                        mesh = mesh_visii, 
                        material = material
                    )
        return entity_obj