Source code for ipymd.visualise.opengl.renderers.triangle

# -*- coding: utf-8 -*-
"""
Created on Mon May 16 09:55:43 2016

@author: cjs14


added patch to allow for transparent surface
"""
import numpy as np

from .base import DefaultRenderer
from ..buffers import VertexBuffer
from ..shaders import set_uniform

from OpenGL.GL import (GL_DYNAMIC_DRAW, GL_VERTEX_ARRAY, GL_NORMAL_ARRAY,
                       GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, GL_FLOAT, GL_TRIANGLES,
                       glEnableClientState, glDrawArrays, 
                       glEnable, glDisable, GL_BLEND, glBlendFunc, 
                       GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, glDepthMask, 
                       GL_TRUE, GL_FALSE,
                       glPolygonMode, GL_FRONT_AND_BACK, GL_FILL, GL_LINE)

[docs]class TriangleRenderer(DefaultRenderer): '''Renders an array of triangles. A lot of renderers are built on this, for example :py:class:`~chemlab.graphics.renderers.SphereRenderer`. The implementation is relatively fast since it's based on VertexBuffers. .. image:: /_static/triangle_renderer.png **Parameters** widget: The parent QChemlabWidget vertices: np.ndarray((NTRIANGLES*3, 3), dtype=float) The triangle vertices, keeping in mind the unwinding order. If the face of the triangle is pointing outwards, the vertices should be provided in clokckwise order. normals: np.ndarray((NTRIANGLES*3, 3), dtype=float) The normals to each of the triangle vertices, used for lighting calculations. colors: np.ndarray((NTRIANGLES*3, 4), dtype=np.uint8) Color for each of the vertices in (r,g,b,a) values in the interval [0, 255] ''' def __init__(self, widget, vertices, normals, colors, shading='phong', transparent=False, wireframe=False): super(TriangleRenderer, self).__init__(widget) n_triangles = len(vertices) # Convert arrays to numpy arrays, float32 precision, # compatible with opengl, and cast to ctypes vertices = np.array(vertices, dtype=np.float32) normals = np.array(normals, dtype=np.float32) colors = np.array(colors, dtype=np.uint8) self.shading = shading self.transparent = transparent self.wireframe = wireframe # Store vertices, colors and normals in 3 different vertex # buffer objects self._vbo_v = VertexBuffer(vertices, GL_DYNAMIC_DRAW) self._vbo_n = VertexBuffer(normals, GL_DYNAMIC_DRAW) self._vbo_c = VertexBuffer(colors, GL_DYNAMIC_DRAW) self._n_triangles = n_triangles
[docs] def setup_shader(self): super(TriangleRenderer, self).setup_shader() shd = {'phong' : 0, 'toon': 1}[self.shading] set_uniform(self.shader, 'shading_type', '1i', shd)
[docs] def draw_vertices(self): # Draw all the vbo defined in set_atoms if self.transparent: glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glDepthMask(GL_FALSE) if self.wireframe: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glEnableClientState(GL_VERTEX_ARRAY) self._vbo_v.bind_vertexes(3, GL_FLOAT) glEnableClientState(GL_NORMAL_ARRAY) self._vbo_n.bind_normals(GL_FLOAT) glEnableClientState(GL_COLOR_ARRAY) self._vbo_c.bind_colors(4, GL_UNSIGNED_BYTE) glDrawArrays(GL_TRIANGLES, 0, self._n_triangles) self._vbo_v.unbind() self._vbo_n.unbind() self._vbo_c.unbind() if self.transparent: glDisable(GL_BLEND) #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glDepthMask(GL_TRUE) if self.wireframe: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
[docs] def update_vertices(self, vertices): """ Update the triangle vertices. """ vertices = np.array(vertices, dtype=np.float32) self._vbo_v.set_data(vertices)
[docs] def update_normals(self, normals): """ Update the triangle normals. """ normals = np.array(normals, dtype=np.float32) self._vbo_n.set_data(normals)
[docs] def update_colors(self, colors): ''' Update the triangle colors. ''' colors = np.array(colors, dtype=np.float32) self._vbo_c.set_data(colors)