Example #1
0
    def set_data(self, vertices=None, faces=None, vertex_colors=None,
                 face_colors=None, color=None, vertex_values=None,
                 meshdata=None):
        """Set the mesh data

        Parameters
        ----------
        vertices : array-like | None
            The vertices.
        faces : array-like | None
            The faces.
        vertex_colors : array-like | None
            Colors to use for each vertex.
        face_colors : array-like | None
            Colors to use for each face.
        color : instance of Color
            The color to use.
        vertex_values : array-like | None
            Values for each vertex.
        meshdata : instance of MeshData | None
            The meshdata.
        """
        if meshdata is not None:
            self._meshdata = meshdata
        else:
            self._meshdata = MeshData(vertices=vertices, faces=faces,
                                      vertex_colors=vertex_colors,
                                      face_colors=face_colors,
                                      vertex_values=vertex_values)
        self._bounds = self._meshdata.get_bounds()
        if color is not None:
            self._color = Color(color)
        self.mesh_data_changed()
Example #2
0
 def __init__(self,
              vertices=None,
              faces=None,
              edges=None,
              vertex_colors=None,
              face_colors=None):
     MeshData.__init__(self,
                       vertices=None,
                       faces=None,
                       edges=None,
                       vertex_colors=None,
                       face_colors=None)
Example #3
0
    def set_data(self,
                 vertices=None,
                 faces=None,
                 vertex_colors=None,
                 face_colors=None,
                 color=None,
                 vertex_values=None,
                 meshdata=None):
        """Set the mesh data

        Parameters
        ----------
        vertices : array-like | None
            The vertices.
        faces : array-like | None
            The faces.
        vertex_colors : array-like | None
            Colors to use for each vertex.
        face_colors : array-like | None
            Colors to use for each face.
        color : instance of Color
            The color to use.
        vertex_values : array-like | None
            Values for each vertex.
        meshdata : instance of MeshData | None
            The meshdata.
        """
        if meshdata is not None:
            self._meshdata = meshdata
        else:
            self._meshdata = MeshData(vertices=vertices,
                                      faces=faces,
                                      vertex_colors=vertex_colors,
                                      face_colors=face_colors,
                                      vertex_values=vertex_values)
        self._bounds = self._meshdata.get_bounds()
        if color is not None:
            self._color = Color(color)
        self.mesh_data_changed()

        if self.variable_vis:
            # Initialize all faces as visible
            if self.mode is 'lines':
                self._visible_verts = np.ones((faces.shape[0], 2, 1),
                                              dtype=np.int8)
            else:
                self._visible_verts = np.ones((faces.shape[0], 3, 1),
                                              dtype=np.int8)
            # Create visibility VertexBuffer
            self.vis_buffer = VertexBuffer()
            self.vis_buffer.set_data(self._visible_verts)
            self.shared_program.vert['vis_vert'] = self.vis_buffer
Example #4
0
    def __init__(self):
        app.Canvas.__init__(self,
                            size=(512, 512),
                            title='Monkey',
                            keys='interactive')
        verts, faces, normals, texcoords = io.read_mesh(
            "../model/monkey/monkey.obj")
        obj = MeshData(verts, faces)

        self.program = gloo.Program(vert=vertex, frag=fragment)

        V = verts.astype('float32')

        F = obj.get_faces().astype('uint32')

        E = obj.get_edges().astype('uint32')

        C = np.array([(1, 1, 1, 1)])
        for i in range(len(V) - 1):
            if i % 2 != 0:
                C = np.append(C, [(1, 1, 1, 1)], axis=0)
            else:
                C = np.append(C, [(0, 0, 0, 1)], axis=0)

        self.program['a_position'] = V
        self.program['a_color'] = C.astype('float32')
        self.F = gloo.IndexBuffer(F)
        self.E = gloo.IndexBuffer(E)

        gloo.set_viewport(0, 0, *self.physical_size)
        gloo.set_polygon_offset(1.0, 1.0)

        # intialize transformation matrix
        view = np.eye(4, dtype=np.float32)
        model = np.eye(4, dtype=np.float32)
        projection = np.eye(4, dtype=np.float32)

        # set view
        view = translate((0, 0, -5))
        self.program['u_model'] = model
        self.program['u_view'] = view
        self.program['u_projection'] = projection

        # bind a timer
        self.timer = app.Timer('auto', self.on_timer)
        self.theta = 0.0
        self.phi = 0.0
        self.timer.start()

        # show the canvas
        self.show()
Example #5
0
    def updateMesh(self,
                   vertices=None,
                   faces=None,
                   colors=None,
                   texture=None,
                   textureCoordinates=None):
        # Set
        if vertices is not None:
            self._meshData.set_vertices(verts=vertices)
        if faces is not None:
            self._meshData.set_faces(faces)
        if colors is not None:
            self._meshData.set_vertex_colors(colors)

        # Update
        if vertices is not None or faces is not None:
            self._vertices = VertexBuffer(
                self._meshData.get_vertices(indexed='faces').astype(
                    np.float32))
        if faces is not None and vertices is not None:
            self._normals = VertexBuffer(
                self._meshData.get_vertex_normals(indexed='faces').astype(
                    np.float32))
        if colors is not None:
            self._colors = VertexBuffer(
                self._meshData.get_vertex_colors(indexed='faces').astype(
                    np.float32))
        if texture is not None:
            self._texture = Texture2D(np.array(texture, dtype=np.float32),
                                      interpolation='linear',
                                      wrapping='mirrored_repeat')
        if textureCoordinates is not None:
            textureMesh = MeshData(vertices=textureCoordinates,
                                   faces=self._meshData.get_faces())
            self._textureCoordinates = VertexBuffer(
                textureMesh.get_vertices(indexed='faces').astype(np.float32))

        # Update GPU - geometry
        self.shared_program.vert['position'] = self._vertices
        self.shared_program.vert['normal'] = self._normals

        # Update GPU - color
        if self._texture is None:
            self.shared_program.vert['color'] = self._colors
        else:
            self.shared_program.vert[
                'textureCoordinates'] = self._textureCoordinates
            self.shared_program['u_objectTexture'] = self._texture
Example #6
0
def create_cylinder(rows,
                    cols,
                    r_angle=0,
                    radius=[1.0, 1.0],
                    length=1.0,
                    offset=False):
    """Create a cylinder

    Parameters
    ----------
    rows : int
        Number of rows.
    cols : int
        Number of columns.
    radius : tuple of float
        Cylinder radii.
    length : float
        Length of the cylinder.
    offset : bool
        Rotate each row by half a column.

    Returns
    -------
    cylinder : MeshData
        Vertices and faces computed for a cylindrical surface.
    """
    verts_n_faces = make_quad_arm(rows=rows,
                                  cols=cols,
                                  r_angle=r_angle,
                                  radius=radius,
                                  length=length,
                                  offset=offset)
    return MeshData(verts_n_faces[0], verts_n_faces[1])
Example #7
0
    def __init__(self, radius=1.0, directions=None, colors=None):

        # Convert spherical to cartesian
        points = np.array([util.tp2xyz(*x) for x in directions])

        # Create mesh
        import scipy.spatial
        ch = scipy.spatial.ConvexHull(points)
        mesh = MeshData(vertices=ch.points, faces=ch.simplices)

        self._mesh = MeshVisual(vertices=mesh.get_vertices(),
                                faces=mesh.get_faces(),
                                vertex_colors=colors)

        CompoundVisual.__init__(self, [self._mesh])
        self.mesh.set_gl_state(depth_test=True)
Example #8
0
def create_quad_frame(rows,
                      cols=8,
                      radius=[1.0, 1.0],
                      length=1.0,
                      offset=False):
    verts, faces, colors = make_quad_frame(rows=rows,
                                           cols=cols,
                                           radius=radius,
                                           length=length,
                                           offset=offset)
    return (MeshData(verts, faces), colors)
Example #9
0
    def _on_data_change(self):
        if len(self.layer._data_view) == 0 or len(self.layer._view_faces) == 0:
            vertices = None
            faces = None
            vertex_values = np.array([0])
        else:
            # Offsetting so pixels now centered
            # coerce to float to solve vispy/vispy#2007
            # reverse order to get zyx instead of xyz
            vertices = np.asarray(self.layer._data_view[:, ::-1],
                                  dtype=np.float32)
            # due to above xyz>zyx, also reverse order of faces to fix handedness of normals
            faces = self.layer._view_faces[:, ::-1]
            vertex_values = self.layer._view_vertex_values

        if (vertices is not None and self.layer._ndisplay == 3
                and self.layer.ndim == 2):
            vertices = np.pad(vertices, ((0, 0), (0, 1)))

        # manually detach filters when we go to 2D to avoid dimensionality issues
        # see comments in napari#3475. The filter is set again after set_data!
        if self.layer._ndisplay == 2:
            filt = self.node.shading_filter
            try:
                self.node.detach(filt)
                self.node.shading = None
                self.node.shading_filter = None
            except ValueError:
                # sometimes we try to detach non-attached filters, which causes a ValueError
                pass

        self.node.set_data(vertices=vertices,
                           faces=faces,
                           vertex_values=vertex_values)

        # disable normals in 2D to avoid shape errors
        if self.layer._ndisplay == 2:
            meshdata = MeshData()
        else:
            meshdata = self.node.mesh_data
        self._meshdata = meshdata

        self._on_face_normals_change()
        self._on_vertex_normals_change()
        self._on_shading_change()

        self.node.update()
        # Call to update order of translation values with new dims:
        self._on_matrix_change()
Example #10
0
    def add_surf(self, surf, color=SKIN_COLOR, vertex_colors=None,
                 values=None, limits_c=None, colormap=COLORMAP, alpha=1):
        """Add surfaces to the visualization.

        Parameters
        ----------
        surf : instance of wonambi.attr.anat.Surf
            surface to be plotted
        color : tuple or ndarray, optional
            4-element tuple, representing RGB and alpha, between 0 and 1
        vertex_colors : ndarray
            ndarray with n vertices x 4 to specify color of each vertex
        values : ndarray, optional
            vector with values for each vertex
        limits_c : tuple of 2 floats, optional
            min and max values to normalize the color
        colormap : str
            one of the colormaps in vispy
        alpha : float
            transparency (1 = opaque)
        """
        colors, limits = _prepare_colors(color=color, values=values,
                                         limits_c=limits_c, colormap=colormap,
                                         alpha=alpha)

        # meshdata uses numpy array, in the correct dimension
        vertex_colors = colors.rgba
        if vertex_colors.shape[0] == 1:
            vertex_colors = tile(vertex_colors, (surf.n_vert, 1))

        meshdata = MeshData(vertices=surf.vert, faces=surf.tri,
                            vertex_colors=vertex_colors)
        mesh = SurfaceMesh(meshdata)

        self._add_mesh(mesh)

        # adjust camera
        surf_center = mean(surf.vert, axis=0)
        if surf_center[0] < 0:
            azimuth = 270
        else:
            azimuth = 90
        self._view.camera.azimuth = azimuth
        self._view.camera.center = surf_center

        self._surf.append(mesh)
Example #11
0
 def test_convert_meshdata(self):
     """Test convert_meshdata function."""
     from vispy.geometry import MeshData
     import vispy.visuals.transforms as vist
     # Force creation of vertices, faces and normals :
     self._creation()
     tup = (self.vertices, self.faces)
     # Compare (vertices + faces) Vs. MeshData :
     mesh1 = convert_meshdata(*tup)
     mesh2 = convert_meshdata(meshdata=MeshData(*tup))
     assert np.array_equal(mesh1[0], mesh2[0])
     assert np.array_equal(mesh1[1], mesh2[1])
     assert np.array_equal(mesh1[2], mesh2[2])
     # Invert normals :
     inv1 = convert_meshdata(*tup, invert_normals=True)[-1]
     assert np.array_equal(inv1, -mesh1[-1])
     # Create transformation :
     tr = vist.MatrixTransform()
     tr.rotate(90, (0, 0, 1))
     convert_meshdata(*tup, transform=tr)[-1]
Example #12
0
class VarVisMeshVisual(MeshVisual):
    """Variable Visibility Mesh visual

    Parameters
    ----------
    vertices : array-like | None
        The vertices.
    faces : array-like | None
        The faces.
    vertex_colors : array-like | None
        Colors to use for each vertex.
    face_colors : array-like | None
        Colors to use for each face.
    color : instance of Color
        The color to use.
    vertex_values : array-like | None
        The values to use for each vertex (for colormapping).
    meshdata : instance of MeshData | None
        The meshdata.
    shading : str | None
        Shading to use.
    mode : str
        The drawing mode.
    variable_vis : bool
        If instance of UpdatableMeshVisual has variable visibility
    **kwargs : dict
        Keyword arguments to pass to `Visual`.
    """
    def __init__(self,
                 nb_boxes,
                 vertices=None,
                 faces=None,
                 vertex_colors=None,
                 face_colors=None,
                 color=(0.5, 0.5, 1, 1),
                 vertex_values=None,
                 meshdata=None,
                 shading=None,
                 mode='triangles',
                 variable_vis=False,
                 **kwargs):

        # Visual.__init__ -> prepare_transforms() -> uses shading

        if shading is not None:
            raise ValueError('"shading" must be "None"')

        self.shading = shading
        self._variable_vis = variable_vis

        if variable_vis:
            Visual.__init__(self,
                            vcode=vertex_template_vis,
                            fcode=fragment_template_vis,
                            **kwargs)
        else:
            Visual.__init__(self,
                            vcode=vertex_template,
                            fcode=fragment_template,
                            **kwargs)

        self.set_gl_state('translucent', depth_test=True, cull_face=False)

        # Define buffers
        self._vertices = VertexBuffer(np.zeros((0, 3), dtype=np.float32))
        self._normals = None
        self._faces = IndexBuffer()
        self._normals = VertexBuffer(np.zeros((0, 3), dtype=np.float32))
        self._ambient_light_color = Color((0.3, 0.3, 0.3, 1.0))
        self._light_dir = (10, 5, -5)
        self._shininess = 1. / 200.
        self._cmap = get_colormap('cubehelix')
        self._clim = 'auto'
        self._mode = mode

        # Uniform color
        self._color = Color(color)

        # primitive mode
        self._draw_mode = mode

        # Init
        self._bounds = None
        # Note we do not call subclass set_data -- often the signatures
        # do no match.
        VarVisMeshVisual.set_data(self,
                                  vertices=vertices,
                                  faces=faces,
                                  vertex_colors=vertex_colors,
                                  face_colors=face_colors,
                                  color=color,
                                  vertex_values=vertex_values,
                                  meshdata=meshdata)

        self.freeze()

    def set_data(self,
                 vertices=None,
                 faces=None,
                 vertex_colors=None,
                 face_colors=None,
                 color=None,
                 vertex_values=None,
                 meshdata=None):
        """Set the mesh data

        Parameters
        ----------
        vertices : array-like | None
            The vertices.
        faces : array-like | None
            The faces.
        vertex_colors : array-like | None
            Colors to use for each vertex.
        face_colors : array-like | None
            Colors to use for each face.
        color : instance of Color
            The color to use.
        vertex_values : array-like | None
            Values for each vertex.
        meshdata : instance of MeshData | None
            The meshdata.
        """
        if meshdata is not None:
            self._meshdata = meshdata
        else:
            self._meshdata = MeshData(vertices=vertices,
                                      faces=faces,
                                      vertex_colors=vertex_colors,
                                      face_colors=face_colors,
                                      vertex_values=vertex_values)
        self._bounds = self._meshdata.get_bounds()
        if color is not None:
            self._color = Color(color)
        self.mesh_data_changed()

        if self.variable_vis:
            # Initialize all faces as visible
            if self.mode is 'lines':
                self._visible_verts = np.ones((faces.shape[0], 2, 1),
                                              dtype=np.int8)
            else:
                self._visible_verts = np.ones((faces.shape[0], 3, 1),
                                              dtype=np.int8)
            # Create visibility VertexBuffer
            self.vis_buffer = VertexBuffer()
            self.vis_buffer.set_data(self._visible_verts)
            self.shared_program.vert['vis_vert'] = self.vis_buffer

    def set_visible_faces(self, idx_vis):
        """Set idx_vis indexes of visible_verts to "visible" (1).
        """
        self.visible_verts[idx_vis, :, :] = 1

    def set_invisible_faces(self, idx_vis):
        """Set idx_vis indexes of visible_verts to "invisible" (0).
        """
        self.visible_verts[idx_vis, :, :] = 0

    def update_vis_buffer(self):
        """Update the visibility VertexBuffer.
        """
        self.vis_buffer.set_data(self.visible_verts)
        self.shared_program.vert['vis_vert'] = self.vis_buffer

    @property
    def visible_verts(self):
        """Bool (float) array indicating which vertices are visible (1) and which are invisible (0).
        """
        return self._visible_verts

    @visible_verts.setter
    def visible_verts(self, visible_verts):
        self._visible_verts = visible_verts

    @property
    def variable_vis(self):
        """Bool if instance of UpdatableMeshVisual posseses variable visibility.
        """
        return self._variable_vis

    @variable_vis.setter
    def variable_vis(self, variable_vis):
        raise ValueError(
            'Not allowed to change "variable_vis" after initialization.')
Example #13
0
def convert_meshdata(vertices=None, faces=None, normals=None, meshdata=None,
                     invert_normals=False, transform=None):
    """Convert mesh data to be compatible with visbrain.

    Parameters
    ----------
    vertices : array_like | None
        Vertices of the template of shape (N, 3) or (N, 3, 3) if indexed by
        faces.
    faces : array_like | None
        Faces of the template of shape (M, 3)
    normals : array_like | None
        The normals to each vertex, with the same shape as vertices.
    meshdata : VisPy.MeshData | None
        VisPy MeshData object.
    invert_normals : bool | False
        If the brain appear to be black, use this parameter to invert normals.
    transform : visPy.transform | None
        VisPy transformation to apply to vertices ans normals.

    Returns
    -------
    vertices : array_like
        Vertices of shape (N, 3)
    faces : array_like
        Faces of the template of shape (M, 3)
    normals : array_like
        The normals of shape (M, 3, 3).
    """
    # Priority to meshdata :
    if meshdata is not None:
        vertices = meshdata.get_vertices()
        faces = meshdata.get_faces()
        normals = meshdata.get_vertex_normals()
        logger.debug('Indexed faces normals converted // extracted')
    else:
        # Check if faces index start at zero (Matlab like):
        if faces.min() != 0:
            faces -= faces.min()
        # Get normals if None :
        if (normals is None) or (normals.ndim != 2):
            md = MeshData(vertices=vertices, faces=faces)
            normals = md.get_vertex_normals()
            logger.debug('Indexed faces normals converted // extracted')
    assert vertices.ndim == 2

    # Invert normals :
    norm_coef = -1. if invert_normals else 1.
    normals *= norm_coef

    # Apply transformation :
    if transform is not None:
        vertices = transform.map(vertices)[..., 0:-1]
        normals = transform.map(normals)[..., 0:-1]

    # Type checking :
    vertices = vispy_array(vertices)
    faces = vispy_array(faces, np.uint32)
    normals = vispy_array(normals)

    return vertices, faces, normals
Example #14
0
 def __init__(self, vertices=None, faces=None, edges=None,
              vertex_colors=None, face_colors=None):
     MeshData.__init__(self, vertices=None, faces=None, edges=None,
                          vertex_colors=None, face_colors=None)
Example #15
0
    def __init__(self,
                 parent=None,
                 children=None,
                 objectID=0,
                 materialID=0,
                 textureCoordinates=None,
                 **kwargs):
        MeshData.__init__(self, **kwargs)

        # Set parent (None=root)
        self._parent = parent

        # Set children
        if children is not None:
            if isinstance(children, list):
                self._children = children
            else:
                self._children = [children]
        else:
            self._children = []

        # Set IDs
        self._objectID = objectID
        self._materialID = materialID

        checkID(self, self._objectID)
        checkID(self, self._materialID)

        # Set empty array for unset data, ndarray for set data
        if self._vertices is None:
            self._vertices = np.empty(0, dtype=np.float32)
            warn('Unset vertices for object ' + self.__repr__(),
                 category=RuntimeWarning)
        elif isinstance(self._vertices, list) or isinstance(
                self._vertices, tuple):
            self._vertices = np.asarray(self._vertices, dtype=np.float32)
        elif not isinstance(self._vertices, np.ndarray):
            raise ValueError('Invalid container type!')

        if self._faces is None:
            self._faces = np.empty(0, dtype=np.uint32)
            warn('Unset faces for object ' + self.__repr__(),
                 category=RuntimeWarning)
        elif isinstance(self._faces, list) or isinstance(self._faces, tuple):
            self._faces = np.asarray(self._faces, dtype=np.uint32)
        elif not isinstance(self._faces, np.ndarray):
            raise ValueError('Invalid container type!')

        if textureCoordinates is None:
            self._textureCoordinates = np.zeros((len(self._vertices), 2),
                                                dtype=np.float32)
            warn('Unset texture coordinates for object ' + self.__repr__(),
                 category=RuntimeWarning)
        elif isinstance(textureCoordinates, list) or isinstance(
                textureCoordinates, tuple):
            self._textureCoordinates = np.asarray(textureCoordinates,
                                                  dtype=np.float32)
        elif isinstance(textureCoordinates, np.ndarray):
            self._textureCoordinates = textureCoordinates
        else:
            raise ValueError('Invalid container type!')
Example #16
0
class MeshVisual(Visual):
    """Mesh visual

    Parameters
    ----------
    vertices : array-like | None
        The vertices.
    faces : array-like | None
        The faces.
    vertex_colors : array-like | None
        Colors to use for each vertex.
    face_colors : array-like | None
        Colors to use for each face.
    color : instance of Color
        The color to use.
    vertex_values : array-like | None
        The values to use for each vertex (for colormapping).
    meshdata : instance of MeshData | None
        The meshdata.
    shading : str | None
        Shading to use. This uses the
        :class:`~vispy.visuals.filters.mesh.ShadingFilter`
        filter introduced in VisPy 0.7. This class provides additional
        features that are available when the filter is attached manually.
        See 'examples/basics/scene/mesh_shading.py' for an example.
    mode : str
        The drawing mode.
    **kwargs : dict
        Keyword arguments to pass to `Visual`.

    Notes
    -----
    Additional functionality is available through filters. Mesh-specific
    filters can be found in the :mod:`vispy.visuals.filters.mesh` module.

    This class emits a `data_updated` event when the mesh data is updated. This
    is used for example by filters for synchronization.

    """

    def __init__(self, vertices=None, faces=None, vertex_colors=None,
                 face_colors=None, color=(0.5, 0.5, 1, 1), vertex_values=None,
                 meshdata=None, shading=None, mode='triangles', **kwargs):
        Visual.__init__(self, vcode=vertex_template, fcode=fragment_template,
                        **kwargs)
        self.set_gl_state('translucent', depth_test=True, cull_face=False)

        self.events.add(data_updated=Event)

        # Define buffers
        self._vertices = VertexBuffer(np.zeros((0, 3), dtype=np.float32))
        self._cmap = get_colormap('cubehelix')
        self._clim = 'auto'

        # Uniform color
        self._color = Color(color)

        # add filters for various modifiers
        self.shading_filter = None
        self.shading = shading

        # Init
        self._bounds = None
        # Note we do not call subclass set_data -- often the signatures
        # do no match.
        MeshVisual.set_data(
            self, vertices=vertices, faces=faces, vertex_colors=vertex_colors,
            face_colors=face_colors, vertex_values=vertex_values,
            meshdata=meshdata, color=color)

        # primitive mode
        self._draw_mode = mode

        self.freeze()

    @property
    def shading(self):
        """The shading method."""
        return self._shading

    @shading.setter
    def shading(self, shading):
        assert shading in (None, 'flat', 'smooth')
        self._shading = shading
        if shading is None and self.shading_filter is None:
            # Delay creation of filter until necessary.
            return
        if self.shading_filter is None:
            from .filters import ShadingFilter
            self.shading_filter = ShadingFilter(shading=shading)
        else:
            self.shading_filter.shading = shading
        self.attach(self.shading_filter)

    def set_data(self, vertices=None, faces=None, vertex_colors=None,
                 face_colors=None, color=None, vertex_values=None,
                 meshdata=None):
        """Set the mesh data

        Parameters
        ----------
        vertices : array-like | None
            The vertices.
        faces : array-like | None
            The faces.
        vertex_colors : array-like | None
            Colors to use for each vertex.
        face_colors : array-like | None
            Colors to use for each face.
        color : instance of Color
            The color to use.
        vertex_values : array-like | None
            Values for each vertex.
        meshdata : instance of MeshData | None
            The meshdata.
        """
        if meshdata is not None:
            self._meshdata = meshdata
        else:
            self._meshdata = MeshData(vertices=vertices, faces=faces,
                                      vertex_colors=vertex_colors,
                                      face_colors=face_colors,
                                      vertex_values=vertex_values)
        self._bounds = self._meshdata.get_bounds()
        if color is not None:
            self._color = Color(color)
        self.mesh_data_changed()

    @property
    def clim(self):
        return (self._clim if isinstance(self._clim, str) else
                tuple(self._clim))

    @clim.setter
    def clim(self, clim):
        if isinstance(clim, str):
            if clim != 'auto':
                raise ValueError('clim must be "auto" if a string')
        else:
            clim = np.array(clim, float)
            if clim.shape != (2,):
                raise ValueError('clim must have two elements')
        self._clim = clim
        self.mesh_data_changed()

    @property
    def _clim_values(self):
        if isinstance(self._clim, str):  # == 'auto'
            if self._meshdata.has_vertex_value():
                clim = self._meshdata.get_vertex_values()
                clim = (np.min(clim), np.max(clim))
            else:
                clim = (0, 1)
        else:
            clim = self._clim
        return clim

    @property
    def cmap(self):
        return self._cmap

    @cmap.setter
    def cmap(self, cmap):
        self._cmap = get_colormap(cmap)
        self.mesh_data_changed()

    @property
    def mode(self):
        """The triangle mode used to draw this mesh.

        Options are:

            * 'triangles': Draw one triangle for every three vertices
              (eg, [1,2,3], [4,5,6], [7,8,9)
            * 'triangle_strip': Draw one strip for every vertex excluding the
              first two (eg, [1,2,3], [2,3,4], [3,4,5])
            * 'triangle_fan': Draw each triangle from the first vertex and the
              last two vertices (eg, [1,2,3], [1,3,4], [1,4,5])
        """
        return self._draw_mode

    @mode.setter
    def mode(self, m):
        modes = ['triangles', 'triangle_strip', 'triangle_fan']
        if m not in modes:
            raise ValueError("Mesh mode must be one of %s" % ', '.join(modes))
        self._draw_mode = m

    @property
    def mesh_data(self):
        """The mesh data"""
        return self._meshdata

    @property
    def color(self):
        """The uniform color for this mesh"""
        return self._color

    @color.setter
    def color(self, c):
        """Set the uniform color of the mesh

        This value is only used if per-vertex or per-face colors are not
        specified.

        Parameters
        ----------
        c : instance of Color
            The color to use.
        """
        if c is not None:
            self._color = Color(c)
        self.mesh_data_changed()

    def mesh_data_changed(self):
        self._data_changed = True
        self.update()

    def _update_data(self):
        md = self.mesh_data

        v = md.get_vertices(indexed='faces')
        if v is None:
            return False
        if v.shape[-1] == 2:
            v = np.concatenate((v, np.zeros((v.shape[:-1] + (1,)))), -1)
        self._vertices.set_data(v, convert=True)
        if md.has_vertex_color():
            colors = md.get_vertex_colors(indexed='faces')
            colors = colors.astype(np.float32)
        elif md.has_face_color():
            colors = md.get_face_colors(indexed='faces')
            colors = colors.astype(np.float32)
        elif md.has_vertex_value():
            colors = md.get_vertex_values(indexed='faces')
            colors = colors.ravel()[:, np.newaxis]
            colors = colors.astype(np.float32)
        else:
            colors = self._color.rgba

        self.shared_program.vert['position'] = self._vertices

        self.shared_program['texture2D_LUT'] = self._cmap.texture_lut() \
            if (hasattr(self._cmap, 'texture_lut')) else None

        # Position input handling
        if v.shape[-1] == 2:
            self.shared_program.vert['to_vec4'] = vec2to4
        elif v.shape[-1] == 3:
            self.shared_program.vert['to_vec4'] = vec3to4
        else:
            raise TypeError("Vertex data must have shape (...,2) or (...,3).")

        # Set the base color.
        #
        # The base color is mixed further by the material filters for texture
        # or shading effects.
        self.shared_program.vert['color_transform'] = \
            _build_color_transform(colors, self._cmap, self._clim_values)
        if colors.ndim == 1:
            self.shared_program.vert['base_color'] = colors
        else:
            self.shared_program.vert['base_color'] = VertexBuffer(colors)

        self._data_changed = False

        self.events.data_updated()

    def _prepare_draw(self, view):
        if self._data_changed:
            if self._update_data() is False:
                return False
            self._data_changed = False

    def draw(self, *args, **kwds):
        Visual.draw(self, *args, **kwds)

    @staticmethod
    def _prepare_transforms(view):
        tr = view.transforms.get_transform()
        view.view_program.vert['transform'] = tr

    def _compute_bounds(self, axis, view):
        if self._bounds is None:
            return None
        if axis >= len(self._bounds):
            return (0, 0)
        else:
            return self._bounds[axis]
Example #17
0
    def __init__(self,
                 vertices,
                 faces,
                 colors=None,
                 texture=None,
                 textureCoordinates=None,
                 light=None,
                 ambientMaterialConstant=0.5,
                 diffuseMaterialConstant=0.4,
                 specularMaterialConstant=0.3,
                 vertexShader=defaultVertexShader,
                 fragmentShader=defaultFragmentShader,
                 camera=None):
        Visual.__init__(self, vertexShader, fragmentShader)

        # Culling mode (for debugging)
        #wrappers.set_cull_face(mode='back')

        # Default arguments
        if colors is None and texture is None:
            colors = np.array([(0.5, 0.5, 0.5)
                               for index in range(vertices.shape[0])],
                              dtype=np.float32)
        elif colors is not None and len(colors) is 3 and (isinstance(
                colors[0], float) or isinstance(colors[0], int)):
            colors = np.array([colors for index in range(len(vertices))],
                              dtype=np.float32)

        if light is None:
            light = SimpleLight(self, color=(1.0, 1.0, 1.0))
        else:
            light = light(self)

        # Geometry setup
        self._meshData = MeshData(vertices=vertices,
                                  faces=faces,
                                  vertex_colors=colors)
        self._vertices = None
        self._colors = None
        self._texture = None
        self._textureCoordinates = None
        self._normals = None
        self._draw_mode = 'triangles'

        self.set_gl_state('opaque', depth_test=True, cull_face=True)

        # Light setup
        self._light = light
        self._camera = camera

        self._ambientMaterialConstant = ambientMaterialConstant
        self._diffuseMaterialConstant = diffuseMaterialConstant
        self._specularMaterialConstant = specularMaterialConstant

        # Initial updates
        self.updateMesh(vertices=vertices,
                        faces=faces,
                        colors=colors,
                        texture=texture,
                        textureCoordinates=textureCoordinates)
        self.updateLight()
Example #18
0
class TriangleMeshVisual(Visual):
    def __init__(self,
                 vertices,
                 faces,
                 colors=None,
                 texture=None,
                 textureCoordinates=None,
                 light=None,
                 ambientMaterialConstant=0.5,
                 diffuseMaterialConstant=0.4,
                 specularMaterialConstant=0.3,
                 vertexShader=defaultVertexShader,
                 fragmentShader=defaultFragmentShader,
                 camera=None):
        Visual.__init__(self, vertexShader, fragmentShader)

        # Culling mode (for debugging)
        #wrappers.set_cull_face(mode='back')

        # Default arguments
        if colors is None and texture is None:
            colors = np.array([(0.5, 0.5, 0.5)
                               for index in range(vertices.shape[0])],
                              dtype=np.float32)
        elif colors is not None and len(colors) is 3 and (isinstance(
                colors[0], float) or isinstance(colors[0], int)):
            colors = np.array([colors for index in range(len(vertices))],
                              dtype=np.float32)

        if light is None:
            light = SimpleLight(self, color=(1.0, 1.0, 1.0))
        else:
            light = light(self)

        # Geometry setup
        self._meshData = MeshData(vertices=vertices,
                                  faces=faces,
                                  vertex_colors=colors)
        self._vertices = None
        self._colors = None
        self._texture = None
        self._textureCoordinates = None
        self._normals = None
        self._draw_mode = 'triangles'

        self.set_gl_state('opaque', depth_test=True, cull_face=True)

        # Light setup
        self._light = light
        self._camera = camera

        self._ambientMaterialConstant = ambientMaterialConstant
        self._diffuseMaterialConstant = diffuseMaterialConstant
        self._specularMaterialConstant = specularMaterialConstant

        # Initial updates
        self.updateMesh(vertices=vertices,
                        faces=faces,
                        colors=colors,
                        texture=texture,
                        textureCoordinates=textureCoordinates)
        self.updateLight()

    # --- Function override ---
    def _prepare_transforms(self, view):
        view.view_program.vert['transform'] = view.get_transform()

    def _prepare_draw(self, view):
        #self.updateMesh()
        self.updateLight()

    # --- State update ---
    def updateMesh(self,
                   vertices=None,
                   faces=None,
                   colors=None,
                   texture=None,
                   textureCoordinates=None):
        # Set
        if vertices is not None:
            self._meshData.set_vertices(verts=vertices)
        if faces is not None:
            self._meshData.set_faces(faces)
        if colors is not None:
            self._meshData.set_vertex_colors(colors)

        # Update
        if vertices is not None or faces is not None:
            self._vertices = VertexBuffer(
                self._meshData.get_vertices(indexed='faces').astype(
                    np.float32))
        if faces is not None and vertices is not None:
            self._normals = VertexBuffer(
                self._meshData.get_vertex_normals(indexed='faces').astype(
                    np.float32))
        if colors is not None:
            self._colors = VertexBuffer(
                self._meshData.get_vertex_colors(indexed='faces').astype(
                    np.float32))
        if texture is not None:
            self._texture = Texture2D(np.array(texture, dtype=np.float32),
                                      interpolation='linear',
                                      wrapping='mirrored_repeat')
        if textureCoordinates is not None:
            textureMesh = MeshData(vertices=textureCoordinates,
                                   faces=self._meshData.get_faces())
            self._textureCoordinates = VertexBuffer(
                textureMesh.get_vertices(indexed='faces').astype(np.float32))

        # Update GPU - geometry
        self.shared_program.vert['position'] = self._vertices
        self.shared_program.vert['normal'] = self._normals

        # Update GPU - color
        if self._texture is None:
            self.shared_program.vert['color'] = self._colors
        else:
            self.shared_program.vert[
                'textureCoordinates'] = self._textureCoordinates
            self.shared_program['u_objectTexture'] = self._texture

    def updateLight(self):
        self.shared_program.frag['ambientLight'] = self._light._ambient
        self.shared_program.frag[
            'ambientMaterialConstant'] = self._ambientMaterialConstant
        self.shared_program.frag[
            'diffuseMaterialConstant'] = self._diffuseMaterialConstant
        self.shared_program.frag[
            'specularMaterialConstant'] = self._specularMaterialConstant
        self.shared_program.frag['lightPos'] = self._light._pos
        self.shared_program.frag['lightColor'] = self._light._color
        self.shared_program.frag['cameraPos'] = np.array(
            self._camera._quaternion.rotate_point([0.0, 3.0, 0.0]),
            dtype=np.float32)
        self.update()