Exemplo n.º 1
0
    def __init__(self, uv, tex, normalizeUV = False, powerOfTwo = False):
        self.uv = uv.copy()

        # Make the parametric domain stretch from (0, 0) to (1, 1)
        if (normalizeUV):
            self.uv -= np.min(self.uv, axis=0)
            dim = np.max(self.uv, axis=0)
            self.uv /= dim

        h, w = tex.shape[0:2]
        s = max(w, h)
        if (powerOfTwo): s = int(np.exp2(np.ceil(np.log2(s))))
        padded = np.pad(tex, [(s - h, 0), (0, s - w), (0, 0)], 'constant', constant_values=128) # pad top, right

        self.dataTex = pythreejs.DataTexture(data=padded, format='RGBAFormat', type='UnsignedByteType')
        self.dataTex.wrapS     = 'ClampToEdgeWrapping'
        self.dataTex.magFilter = 'LinearFilter'
        self.dataTex.minFilter = 'LinearMipMapLinearFilter'
        self.dataTex.generateMipmaps = True
        self.dataTex.flipY = True

        self.uv *= np.array([float(w) / s, float(h) / s])
Exemplo n.º 2
0
def to_surf_mesh(actor, surf, mapper, prop, add_attr={}):
    """Convert a pyvista surface to a buffer geometry.

    General Notes
    -------------

    * THREE.BufferGeometry expects position and index attributes
      representing a triangulated mesh points and face indices or just
      a position array representing individual faces of a mesh.
    * The normals attribute is needed for physically based rendering,
      but not for the other mesh types.
    * Colors must be a RGB array with one value per point.

    Shading Notes
    -------------
    To match VTK, the following materials are used to match VTK's shading:

    * MeshPhysicalMaterial when physically based rendering is enabled
    * MeshPhongMaterial when physically based rendering is disabled,
      but lighting is enabled.
    * MeshBasicMaterial when lighting is disabled.

    """
    # convert to an all-triangular surface
    if surf.is_all_triangles():
        trimesh = surf
    else:
        trimesh = surf.triangulate()

    position = array_to_float_buffer(trimesh.points)

    # convert to minimum index type
    face_ind = trimesh.faces.reshape(-1, 4)[:, 1:]
    index = cast_to_min_size(face_ind, trimesh.n_points)
    attr = {
        'position': position,
        'index': index,
    }

    if prop.GetInterpolation():  # something other than flat shading
        attr['normal'] = buffer_normals(trimesh)

    # extract point/cell scalars for coloring
    colors = None
    scalar_mode = mapper.GetScalarModeAsString()
    if scalar_mode == 'UsePointData':
        colors = map_scalars(mapper, trimesh.point_data.active_scalars)
    elif scalar_mode == 'UseCellData':
        # special handling for RGBA
        if mapper.GetColorMode() == 2:
            scalars = trimesh.cell_data.active_scalars.repeat(3, axis=0)
            scalars = scalars.astype(np.float32, copy=False)
            colors = scalars[:, :3] / 255  # ignore alpha
        else:
            # must repeat for each triangle
            scalars = trimesh.cell_data.active_scalars.repeat(3)
            colors = map_scalars(mapper, scalars)

        position = array_to_float_buffer(trimesh.points[face_ind])
        attr = {'position': position}

    # add colors to the buffer geometry attributes
    if colors is not None:
        attr['color'] = array_to_float_buffer(colors)

    # texture coordinates
    t_coords = trimesh.active_t_coords
    if t_coords is not None:
        attr['uv'] = array_to_float_buffer(t_coords)

    # TODO: Convert PBR textures
    # base_color_texture = prop.GetTexture("albedoTex")
    # orm_texture = prop.GetTexture("materialTex")
    # anisotropy_texture = prop.GetTexture("anisotropyTex")
    # normal_texture = prop.GetTexture("normalTex")
    # emissive_texture = prop.GetTexture("emissiveTex")
    # coatnormal_texture = prop.GetTexture("coatNormalTex")
    if prop.GetNumberOfTextures():  # pragma: no cover
        warnings.warn(
            'pythreejs converter does not support PBR textures (yet).')

    # create base buffer geometry
    surf_geo = tjs.BufferGeometry(attributes=attr)

    # add texture to the surface buffer if available
    texture = actor.GetTexture()
    tjs_texture = None
    if texture is not None:
        wrapped_tex = pv.wrap(texture.GetInput())
        data = wrapped_tex.active_scalars
        dim = (wrapped_tex.dimensions[0], wrapped_tex.dimensions[1],
               data.shape[1])
        data = data.reshape(dim)
        fmt = "RGBFormat" if data.shape[1] == 3 else "RGBAFormat"

        # Create data texture and catch invalid warning
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore",
                                    message="Given trait value dtype")
            tjs_texture = tjs.DataTexture(data=data,
                                          format="RGBFormat",
                                          type="UnsignedByteType")

    # these attributes are always used regardless of the material
    shared_attr = {
        'vertexColors': get_coloring(mapper, trimesh),
        'wireframe': prop.GetRepresentation() == 1,
        'opacity': prop.GetOpacity(),
        'wireframeLinewidth': prop.GetLineWidth(),
        # 'side': 'DoubleSide'  # enabling seems to mess with textures
    }

    if colors is None:
        shared_attr['color'] = color_to_hex(prop.GetColor())

    if tjs_texture is not None:
        shared_attr['map'] = tjs_texture
    else:
        shared_attr['side'] = 'DoubleSide'

    if prop.GetOpacity() < 1.0:
        shared_attr['transparent'] = True

    if prop.GetInterpolation() == 3:  # using physically based rendering
        material = tjs.MeshPhysicalMaterial(flatShading=False,
                                            roughness=prop.GetRoughness(),
                                            metalness=prop.GetMetallic(),
                                            reflectivity=0,
                                            **shared_attr,
                                            **add_attr)
    elif prop.GetLighting():
        # specular disabled to fix lighting issues
        material = tjs.MeshPhongMaterial(
            shininess=0,
            flatShading=prop.GetInterpolation() == 0,
            specular=color_to_hex((0, 0, 0)),
            reflectivity=0,
            **shared_attr,
            **add_attr)
    else:  # no lighting
        material = tjs.MeshBasicMaterial(**shared_attr, **add_attr)

    return tjs.Mesh(geometry=surf_geo, material=material)
Exemplo n.º 3
0
    def add_mesh(self, v, f, c=None, uv=None, shading={}, texture_data=None):
        sh = self.__get_shading(shading)
        mesh_obj = {}

        #it is a tet
        if v.shape[1] == 3 and f.shape[1] == 4:
            f_tmp = np.ndarray([f.shape[0]*4, 3], dtype=f.dtype)
            for i in range(f.shape[0]):
                f_tmp[i*4+0] = np.array([f[i][1], f[i][0], f[i][2]])
                f_tmp[i*4+1] = np.array([f[i][0], f[i][1], f[i][3]])
                f_tmp[i*4+2] = np.array([f[i][1], f[i][2], f[i][3]])
                f_tmp[i*4+3] = np.array([f[i][2], f[i][0], f[i][3]])
            f = f_tmp

        if v.shape[1] == 2:
            v = np.append(v, np.zeros([v.shape[0], 1]), 1)


        # Type adjustment vertices
        v = v.astype("float32", copy=False)

        # Color setup
        colors, coloring = self.__get_colors(v, f, c, sh)

        # Type adjustment faces and colors
        c = colors.astype("float32", copy=False)

        # Material and geometry setup
        ba_dict = {"color": p3s.BufferAttribute(c)}
        if coloring == "FaceColors":
            verts = np.zeros((f.shape[0]*3, 3), dtype="float32")
            for ii in range(f.shape[0]):
                #print(ii*3, f[ii])
                verts[ii*3] = v[f[ii,0]]
                verts[ii*3+1] = v[f[ii,1]]
                verts[ii*3+2] = v[f[ii,2]]
            v = verts
        else:
            f = f.astype("uint32", copy=False).ravel()
            ba_dict["index"] = p3s.BufferAttribute(f, normalized=False)

        ba_dict["position"] = p3s.BufferAttribute(v, normalized=False)

        if type(uv) != type(None):
            uv = (uv - np.min(uv)) / (np.max(uv) - np.min(uv))
            if texture_data is None:
                texture_data = gen_checkers(20, 20)
            tex = p3s.DataTexture(data=texture_data, format="RGBFormat", type="FloatType")
            material = p3s.MeshStandardMaterial(map=tex, reflectivity=sh["reflectivity"], side=sh["side"],
                    roughness=sh["roughness"], metalness=sh["metalness"], flatShading=sh["flat"],
                    polygonOffset=True, polygonOffsetFactor= 1, polygonOffsetUnits=5)
            ba_dict["uv"] = p3s.BufferAttribute(uv.astype("float32", copy=False))
        else:
            material = p3s.MeshStandardMaterial(vertexColors=coloring, reflectivity=sh["reflectivity"],
                    side=sh["side"], roughness=sh["roughness"], metalness=sh["metalness"],
                    flatShading=sh["flat"],
                    polygonOffset=True, polygonOffsetFactor= 1, polygonOffsetUnits=5)

        geometry = p3s.BufferGeometry(attributes=ba_dict)

        if coloring == "VertexColors":
            geometry.exec_three_obj_method('computeVertexNormals')
        else:
            geometry.exec_three_obj_method('computeFaceNormals')

        # Mesh setup
        mesh = p3s.Mesh(geometry=geometry, material=material)

        # Wireframe setup
        mesh_obj["wireframe"] = None
        if sh["wireframe"]:
            wf_geometry = p3s.WireframeGeometry(mesh.geometry) # WireframeGeometry
            wf_material = p3s.LineBasicMaterial(color=sh["wire_color"], linewidth=sh["wire_width"])
            wireframe = p3s.LineSegments(wf_geometry, wf_material)
            mesh.add(wireframe)
            mesh_obj["wireframe"] = wireframe

        # Bounding box setup
        if sh["bbox"]:
            v_box, f_box = self.__get_bbox(v)
            _, bbox = self.add_edges(v_box, f_box, sh, mesh)
            mesh_obj["bbox"] = [bbox, v_box, f_box]

        # Object setup
        mesh_obj["max"] = np.max(v, axis=0)
        mesh_obj["min"] = np.min(v, axis=0)
        mesh_obj["geometry"] = geometry
        mesh_obj["mesh"] = mesh
        mesh_obj["material"] = material
        mesh_obj["type"] = "Mesh"
        mesh_obj["shading"] = sh
        mesh_obj["coloring"] = coloring
        mesh_obj["arrays"] = [v, f, c] # TODO replays with proper storage or remove if not needed

        return self.__add_object(mesh_obj)
Exemplo n.º 4
0
    def __init__(self,
                 U,
                 grid,
                 render_size,
                 color_map,
                 title,
                 bounding_box=([0, 0], [1, 1]),
                 codim=2,
                 vmin=None,
                 vmax=None):
        assert grid.reference_element in (triangle, square)
        assert grid.dim == 2
        assert codim in (0, 2)
        self.layout = Layout(min_width=str(render_size[0]),
                             min_height=str(render_size[1]),
                             margin='0px 0px 0px 20px ')
        self.grid = grid
        self.codim = codim
        self.vmin, self.vmax = vmin, vmax

        subentities, coordinates, self.entity_map = flatten_grid(grid)

        if grid.reference_element == triangle:
            if codim == 2:
                vertices = np.zeros((len(coordinates), 3))
                vertices[:, :-1] = coordinates
                indices = subentities
            else:
                vertices = np.zeros((len(subentities) * 3, 3))
                VERTEX_POS = coordinates[subentities]
                vertices[:, 0:2] = VERTEX_POS.reshape((-1, 2))
                indices = np.arange(len(subentities) * 3, dtype=np.uint32)
        else:
            if codim == 2:
                vertices = np.zeros((len(coordinates), 3))
                vertices[:, :-1] = coordinates
                indices = np.vstack(
                    (subentities[:, 0:3], subentities[:, [0, 2, 3]]))
            else:
                num_entities = len(subentities)
                vertices = np.zeros((num_entities * 6, 3))
                VERTEX_POS = coordinates[subentities]
                vertices[0:num_entities * 3,
                         0:2] = VERTEX_POS[:, 0:3, :].reshape((-1, 2))
                vertices[num_entities * 3:,
                         0:2] = VERTEX_POS[:, [0, 2, 3], :].reshape((-1, 2))
                indices = np.arange(len(subentities) * 6, dtype=np.uint32)

        max_tex_size = 512
        cm = color_map(np.linspace(0, 1, max_tex_size)).astype(np.float32)
        cm.resize((max_tex_size, 1, 4))
        color_map = p3js.DataTexture(cm,
                                     format='RGBAFormat',
                                     width=max_tex_size,
                                     height=1,
                                     type='FloatType')
        uniforms = dict(colormap={'value': color_map, 'type': 'sampler2D'}, )
        self.material = p3js.ShaderMaterial(
            vertexShader=RENDER_VERTEX_SHADER,
            fragmentShader=RENDER_FRAGMENT_SHADER,
            uniforms=uniforms,
        )

        self.buffer_vertices = p3js.BufferAttribute(vertices.astype(
            np.float32),
                                                    normalized=False)
        self.buffer_faces = p3js.BufferAttribute(indices.astype(
            np.uint32).ravel(),
                                                 normalized=False)
        self.meshes = []
        self._setup_scene(bounding_box, render_size)
        if config.is_nbconvert():
            # need to ensure all data is loaded before cell execution is over
            class LoadDummy:
                def done(self):
                    return True

            self._load_data(U)
            self.load = LoadDummy()
        else:
            self.load = asyncio.ensure_future(self._async_load_data(U))

        self._last_idx = None
        super().__init__(children=[
            self.renderer,
        ])