Added basic wireframe mesh drawing

This commit is contained in:
Luke Campagnola 2013-05-29 14:33:14 -04:00
parent af4980d153
commit ba56899a36
3 changed files with 98 additions and 25 deletions

View File

@ -83,6 +83,16 @@ m3 = gl.GLMeshItem(meshdata=md, smooth=False)#, shader='balloon')
w.addItem(m3)
# Example 4:
# wireframe
md = gl.MeshData.sphere(rows=4, cols=8)
m4 = gl.GLMeshItem(meshdata=md, smooth=False, drawFaces=False, drawEdges=True, edgeColor=(1,1,1,1))
m4.translate(0,10,0)
w.addItem(m4)

View File

@ -44,7 +44,7 @@ class MeshData(object):
## mappings between vertexes, faces, and edges
self._faces = None # Nx3 array of indexes into self._vertexes specifying three vertexes for each face
self._edges = None
self._edges = None # Nx2 array of indexes into self._vertexes specifying two vertexes per edge
self._vertexFaces = None ## maps vertex ID to a list of face IDs (inverse mapping of _faces)
self._vertexEdges = None ## maps vertex ID to a list of edge IDs (inverse mapping of _edges)
@ -143,12 +143,19 @@ class MeshData(object):
def faces(self):
"""Return an array (Nf, 3) of vertex indexes, three per triangular face in the mesh."""
return self._faces
def edges(self):
"""Return an array (Nf, 3) of vertex indexes, two per edge in the mesh."""
if self._edges is None:
self._computeEdges()
return self._edges
def setFaces(self, faces):
"""Set the (Nf, 3) array of faces. Each rown in the array contains
three indexes into the vertex array, specifying the three corners
of a triangular face."""
self._faces = faces
self._edges = None
self._vertexFaces = None
self._vertexesIndexedByFaces = None
self.resetNormals()
@ -418,6 +425,25 @@ class MeshData(object):
#"""
#pass
def _computeEdges(self):
## generate self._edges from self._faces
#print self._faces
nf = len(self._faces)
edges = np.empty(nf*3, dtype=[('i', np.uint, 2)])
edges['i'][0:nf] = self._faces[:,:2]
edges['i'][nf:2*nf] = self._faces[:,1:3]
edges['i'][-nf:,0] = self._faces[:,2]
edges['i'][-nf:,1] = self._faces[:,0]
# sort per-edge
mask = edges['i'][:,0] > edges['i'][:,1]
edges['i'][mask] = edges['i'][mask][:,::-1]
# remove duplicate entries
self._edges = np.unique(edges)['i']
#print self._edges
def save(self):
"""Serialize this mesh to a string appropriate for disk storage"""
import pickle

View File

@ -22,9 +22,15 @@ class GLMeshItem(GLGraphicsItem):
Arguments
meshdata MeshData object from which to determine geometry for
this item.
color Default color used if no vertex or face colors are
specified.
shader Name of shader program to use (None for no shader)
color Default face color used if no vertex or face colors
are specified.
edgeColor Default edge color to use if no edge colors are
specified in the mesh data.
drawEdges If True, a wireframe mesh will be drawn.
(default=False)
drawFaces If True, mesh faces are drawn. (default=True)
shader Name of shader program to use when drawing faces.
(None for no shader)
smooth If True, normal vectors are computed for each vertex
and interpolated within each face.
computeNormals If False, then computation of normal vectors is
@ -35,6 +41,9 @@ class GLMeshItem(GLGraphicsItem):
self.opts = {
'meshdata': None,
'color': (1., 1., 1., 1.),
'drawEdges': False,
'drawFaces': True,
'edgeColor': (0.5, 0.5, 0.5, 1.0),
'shader': None,
'smooth': True,
'computeNormals': True,
@ -100,6 +109,8 @@ class GLMeshItem(GLGraphicsItem):
self.faces = None
self.normals = None
self.colors = None
self.edges = None
self.edgeColors = None
self.update()
def parseMeshData(self):
@ -137,6 +148,9 @@ class GLMeshItem(GLGraphicsItem):
elif md.hasFaceColor():
self.colors = md.faceColors(indexed='faces')
if self.opts['drawEdges']:
self.edges = md.edges()
self.edgeVerts = md.vertexes()
return
def paint(self):
@ -144,19 +158,52 @@ class GLMeshItem(GLGraphicsItem):
self.parseMeshData()
with self.shader():
verts = self.vertexes
norms = self.normals
color = self.colors
faces = self.faces
if verts is None:
return
if self.opts['drawFaces']:
with self.shader():
verts = self.vertexes
norms = self.normals
color = self.colors
faces = self.faces
if verts is None:
return
glEnableClientState(GL_VERTEX_ARRAY)
try:
glVertexPointerf(verts)
if self.colors is None:
color = self.opts['color']
if isinstance(color, QtGui.QColor):
glColor4f(*pg.glColor(color))
else:
glColor4f(*color)
else:
glEnableClientState(GL_COLOR_ARRAY)
glColorPointerf(color)
if norms is not None:
glEnableClientState(GL_NORMAL_ARRAY)
glNormalPointerf(norms)
if faces is None:
glDrawArrays(GL_TRIANGLES, 0, np.product(verts.shape[:-1]))
else:
faces = faces.astype(np.uint).flatten()
glDrawElements(GL_TRIANGLES, faces.shape[0], GL_UNSIGNED_INT, faces)
finally:
glDisableClientState(GL_NORMAL_ARRAY)
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)
if self.opts['drawEdges']:
verts = self.edgeVerts
edges = self.edges
glEnableClientState(GL_VERTEX_ARRAY)
try:
glVertexPointerf(verts)
if self.colors is None:
color = self.opts['color']
if self.edgeColors is None:
color = self.opts['edgeColor']
if isinstance(color, QtGui.QColor):
glColor4f(*pg.glColor(color))
else:
@ -164,19 +211,9 @@ class GLMeshItem(GLGraphicsItem):
else:
glEnableClientState(GL_COLOR_ARRAY)
glColorPointerf(color)
if norms is not None:
glEnableClientState(GL_NORMAL_ARRAY)
glNormalPointerf(norms)
if faces is None:
glDrawArrays(GL_TRIANGLES, 0, np.product(verts.shape[:-1]))
else:
faces = faces.astype(np.uint).flatten()
glDrawElements(GL_TRIANGLES, faces.shape[0], GL_UNSIGNED_INT, faces)
edges = edges.flatten()
glDrawElements(GL_LINES, edges.shape[0], GL_UNSIGNED_INT, edges)
finally:
glDisableClientState(GL_NORMAL_ARRAY)
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)