# -*- 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)