Added basic wireframe mesh drawing
This commit is contained in:
parent
af4980d153
commit
ba56899a36
|
@ -83,6 +83,16 @@ m3 = gl.GLMeshItem(meshdata=md, smooth=False)#, shader='balloon')
|
||||||
w.addItem(m3)
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ class MeshData(object):
|
||||||
|
|
||||||
## mappings between vertexes, faces, and edges
|
## mappings between vertexes, faces, and edges
|
||||||
self._faces = None # Nx3 array of indexes into self._vertexes specifying three vertexes for each face
|
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._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)
|
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):
|
def faces(self):
|
||||||
"""Return an array (Nf, 3) of vertex indexes, three per triangular face in the mesh."""
|
"""Return an array (Nf, 3) of vertex indexes, three per triangular face in the mesh."""
|
||||||
return self._faces
|
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):
|
def setFaces(self, faces):
|
||||||
"""Set the (Nf, 3) array of faces. Each rown in the array contains
|
"""Set the (Nf, 3) array of faces. Each rown in the array contains
|
||||||
three indexes into the vertex array, specifying the three corners
|
three indexes into the vertex array, specifying the three corners
|
||||||
of a triangular face."""
|
of a triangular face."""
|
||||||
self._faces = faces
|
self._faces = faces
|
||||||
|
self._edges = None
|
||||||
self._vertexFaces = None
|
self._vertexFaces = None
|
||||||
self._vertexesIndexedByFaces = None
|
self._vertexesIndexedByFaces = None
|
||||||
self.resetNormals()
|
self.resetNormals()
|
||||||
|
@ -418,6 +425,25 @@ class MeshData(object):
|
||||||
#"""
|
#"""
|
||||||
#pass
|
#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):
|
def save(self):
|
||||||
"""Serialize this mesh to a string appropriate for disk storage"""
|
"""Serialize this mesh to a string appropriate for disk storage"""
|
||||||
import pickle
|
import pickle
|
||||||
|
|
|
@ -22,9 +22,15 @@ class GLMeshItem(GLGraphicsItem):
|
||||||
Arguments
|
Arguments
|
||||||
meshdata MeshData object from which to determine geometry for
|
meshdata MeshData object from which to determine geometry for
|
||||||
this item.
|
this item.
|
||||||
color Default color used if no vertex or face colors are
|
color Default face color used if no vertex or face colors
|
||||||
specified.
|
are specified.
|
||||||
shader Name of shader program to use (None for no shader)
|
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
|
smooth If True, normal vectors are computed for each vertex
|
||||||
and interpolated within each face.
|
and interpolated within each face.
|
||||||
computeNormals If False, then computation of normal vectors is
|
computeNormals If False, then computation of normal vectors is
|
||||||
|
@ -35,6 +41,9 @@ class GLMeshItem(GLGraphicsItem):
|
||||||
self.opts = {
|
self.opts = {
|
||||||
'meshdata': None,
|
'meshdata': None,
|
||||||
'color': (1., 1., 1., 1.),
|
'color': (1., 1., 1., 1.),
|
||||||
|
'drawEdges': False,
|
||||||
|
'drawFaces': True,
|
||||||
|
'edgeColor': (0.5, 0.5, 0.5, 1.0),
|
||||||
'shader': None,
|
'shader': None,
|
||||||
'smooth': True,
|
'smooth': True,
|
||||||
'computeNormals': True,
|
'computeNormals': True,
|
||||||
|
@ -100,6 +109,8 @@ class GLMeshItem(GLGraphicsItem):
|
||||||
self.faces = None
|
self.faces = None
|
||||||
self.normals = None
|
self.normals = None
|
||||||
self.colors = None
|
self.colors = None
|
||||||
|
self.edges = None
|
||||||
|
self.edgeColors = None
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def parseMeshData(self):
|
def parseMeshData(self):
|
||||||
|
@ -137,6 +148,9 @@ class GLMeshItem(GLGraphicsItem):
|
||||||
elif md.hasFaceColor():
|
elif md.hasFaceColor():
|
||||||
self.colors = md.faceColors(indexed='faces')
|
self.colors = md.faceColors(indexed='faces')
|
||||||
|
|
||||||
|
if self.opts['drawEdges']:
|
||||||
|
self.edges = md.edges()
|
||||||
|
self.edgeVerts = md.vertexes()
|
||||||
return
|
return
|
||||||
|
|
||||||
def paint(self):
|
def paint(self):
|
||||||
|
@ -144,19 +158,52 @@ class GLMeshItem(GLGraphicsItem):
|
||||||
|
|
||||||
self.parseMeshData()
|
self.parseMeshData()
|
||||||
|
|
||||||
with self.shader():
|
if self.opts['drawFaces']:
|
||||||
verts = self.vertexes
|
with self.shader():
|
||||||
norms = self.normals
|
verts = self.vertexes
|
||||||
color = self.colors
|
norms = self.normals
|
||||||
faces = self.faces
|
color = self.colors
|
||||||
if verts is None:
|
faces = self.faces
|
||||||
return
|
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)
|
glEnableClientState(GL_VERTEX_ARRAY)
|
||||||
try:
|
try:
|
||||||
glVertexPointerf(verts)
|
glVertexPointerf(verts)
|
||||||
|
|
||||||
if self.colors is None:
|
if self.edgeColors is None:
|
||||||
color = self.opts['color']
|
color = self.opts['edgeColor']
|
||||||
if isinstance(color, QtGui.QColor):
|
if isinstance(color, QtGui.QColor):
|
||||||
glColor4f(*pg.glColor(color))
|
glColor4f(*pg.glColor(color))
|
||||||
else:
|
else:
|
||||||
|
@ -164,19 +211,9 @@ class GLMeshItem(GLGraphicsItem):
|
||||||
else:
|
else:
|
||||||
glEnableClientState(GL_COLOR_ARRAY)
|
glEnableClientState(GL_COLOR_ARRAY)
|
||||||
glColorPointerf(color)
|
glColorPointerf(color)
|
||||||
|
edges = edges.flatten()
|
||||||
|
glDrawElements(GL_LINES, edges.shape[0], GL_UNSIGNED_INT, edges)
|
||||||
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:
|
finally:
|
||||||
glDisableClientState(GL_NORMAL_ARRAY)
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY)
|
glDisableClientState(GL_VERTEX_ARRAY)
|
||||||
glDisableClientState(GL_COLOR_ARRAY)
|
glDisableClientState(GL_COLOR_ARRAY)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user