Skip to content

Commit

Permalink
Fix behavior and update interface
Browse files Browse the repository at this point in the history
- Adapt indexing mode to changes in MeshVisual
- Add setters for texture and texcoords
- Add switch for displaying the texture
  • Loading branch information
asnt committed Mar 28, 2018
1 parent 9ed0c96 commit 33db5c8
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 27 deletions.
11 changes: 9 additions & 2 deletions examples/basics/scene/mesh_texture.py
Expand Up @@ -29,8 +29,8 @@
mesh = Mesh(vertices, faces, shading=shading, color='lightgreen')
view.add(mesh)

tex = TextureFilter(texture, texcoords)
mesh.attach(tex)
texture_filter = TextureFilter(texture, texcoords)
mesh.attach(texture_filter)

mesh.light_dir = (0, -1, 0)
initial_light_dir = view.camera.transform.imap(mesh.light_dir)[:3]
Expand All @@ -43,6 +43,13 @@ def on_mouse_move(event):
mesh.light_dir = transform.map(initial_light_dir)[:3]


@canvas.events.key_press.connect
def on_key_press(event):
if event.key == "t":
texture_filter.enabled = not texture_filter.enabled
mesh.update()


canvas.show()

if __name__ == "__main__":
Expand Down
107 changes: 84 additions & 23 deletions vispy/visuals/filters/mesh.py
@@ -1,48 +1,109 @@
import weakref

import numpy as np
from vispy.gloo import Texture2D, VertexBuffer
from vispy.visuals.shaders import Function, Varying
import numpy as np


class TextureFilter(object):

def __init__(self, texture, texcoords):
self.texture = texture
self.texcoords = texcoords
self._texcoords = VertexBuffer(np.zeros((0, 2), dtype=np.float32))
self._texcoord_varying = Varying('v_texcoord', 'vec2')
self.apply_coords = Function("""
void apply_coords() {
def __init__(self, texture, texcoords, enabled=True):
"""Apply a texture on a mesh.
Parameters
----------
texture : (M, N) or (M, N, C) array
The 2D texture image.
texcoords : (N, 2) array
The texture coordinates.
enabled : bool
Whether the display of the texture is enabled.
"""
self.pass_coords = Function("""
void pass_coords() {
$v_texcoords = $texcoords;
}
""")

self.apply_texture = Function("""
void apply_texture() {
gl_FragColor *= texture2D($u_texture, $texcoord);
if ($enabled == 1) {
gl_FragColor *= texture2D($u_texture, $texcoords);
}
}
""")

self.coords_expr = self.apply_coords()
self._texcoord_varying = Varying('v_texcoord', 'vec2')
self.pass_coords['v_texcoords'] = self._texcoord_varying
self.apply_texture['texcoords'] = self._texcoord_varying
self._texcoords_buffer = VertexBuffer(
np.zeros((0, 2), dtype=np.float32)
)
self.pass_coords['texcoords'] = self._texcoords_buffer
self.coords_expr = self.pass_coords()
self.texture_expr = self.apply_texture()

self._attached = False
self.enabled = enabled
self.texture = texture
self.texcoords = texcoords

@property
def enabled(self):
"""True to display the texture, False to disable."""
return self._enabled

@enabled.setter
def enabled(self, enabled):
self._enabled = enabled
self.apply_texture['enabled'] = 1 if enabled else 0

@property
def texture(self):
"""The texture image."""
return self._texture

@texture.setter
def texture(self, texture):
self._texture = texture
self.apply_texture['u_texture'] = Texture2D(texture)

@property
def texcoords(self):
"""The texture coordinates as an (N, 2) array of floats."""
return self._texcoords

@texcoords.setter
def texcoords(self, texcoords):
self._texcoords = texcoords
self._update_texcoords_buffer(texcoords)

def _update_texcoords_buffer(self, texcoords):
if not self._attached:
return
md = self._visual().mesh_data
if self._visual().shading == 'smooth' and not md.has_face_indexed_data():
tc = texcoords
else:
tc = texcoords[md.get_faces()]
self._texcoords_buffer.set_data(tc, convert=True)

def _on_mesh_data_updated(self, event):
self._update_texcoords_buffer(self._texcoords)

def _attach(self, visual):
# vertex shader
visual.events.data_updated.connect(self._on_mesh_data_updated)

vert_pre = visual._get_hook('vert', 'pre')
vert_pre.add(self.coords_expr)
if visual.shading == 'smooth':
tc = self.texcoords
else:
tc = self.texcoords[visual.mesh_data.get_faces()]
self._texcoords.set_data(tc, convert=True)
self.apply_coords['texcoords'] = self._texcoords
self.apply_coords['v_texcoords'] = self._texcoord_varying

# fragment shader
frag_post = visual._get_hook('frag', 'post')
frag_post.add(self.texture_expr)
self.apply_texture['texcoord'] = self._texcoord_varying
self.apply_texture['u_texture'] = Texture2D(self.texture)

self._attached = True
self._visual = weakref.ref(visual)

self._update_texcoords_buffer(self._texcoords)

def _detach(self, visual):
visual._get_hook('vert', 'pre').remove(self.coords_expr)
visual._get_hook('frag', 'post').remove(self.texture_expr)
self._attached = False
13 changes: 11 additions & 2 deletions vispy/visuals/mesh.py
Expand Up @@ -17,6 +17,7 @@
from ..geometry import MeshData
from ..color import Color, get_colormap
from ..ext.six import string_types
from ..util.event import Event


# Shaders for lit rendering (using phong shading)
Expand Down Expand Up @@ -173,6 +174,11 @@ class MeshVisual(Visual):
The drawing mode.
**kwargs : dict
Keyword arguments to pass to `Visual`.
Events
------
data_updated
Emitted when the mesh data is updated.
"""
def __init__(self, vertices=None, faces=None, vertex_colors=None,
face_colors=None, color=(0.5, 0.5, 1, 1), vertex_values=None,
Expand All @@ -197,6 +203,8 @@ def __init__(self, vertices=None, faces=None, vertex_colors=None,
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._normals = None
Expand Down Expand Up @@ -351,8 +359,7 @@ def mesh_data_changed(self):
def _update_data(self):
md = self.mesh_data
# Update vertex/index buffers
# if self.shading == 'smooth' and not md.has_face_indexed_data():
if self.shading == 'smooth':
if self.shading == 'smooth' and not md.has_face_indexed_data():
v = md.get_vertices()
if v is None:
return False
Expand Down Expand Up @@ -443,6 +450,8 @@ def _update_data(self):

self._data_changed = False

self.events.data_updated()

@property
def shininess(self):
"""The shininess"""
Expand Down

0 comments on commit 33db5c8

Please sign in to comment.