~mcfletch/openglcontext/trunk : /OpenGLContext/scenegraph/arraygeometry.py (revision 351)

Line Revision Contents
1 1
"""Vertex-array-based geometry node for faces, lines and points"""
2
from OpenGL.GL import *
3
from OpenGLContext.arrays import *
4
import polygonsort
5
from OpenGLContext import triangleutilities
6
from OpenGLContext.debug.logs import geometry_log
7
from OpenGL.arrays import vbo
8
9
try:
10
	contiguous
11
except NameError:
12
	def contiguous( source, typecode=None ):
13
		"""Force source to be a contiguous array"""
14
		if isinstance( source, ArrayType):
15
			if not hasattr(source, 'iscontiguous' ):
16
				# XXX apparently numpy arrays are always contiguous???
17
				return source
18
			if source.iscontiguous() and (typecode is None or typecode==typeCode(source)):
19
				return source
20
			else:
21
				return array(source,typecode or typeCode(source))
22
		elif typecode:
23
			return array( source, typecode )
24
		else:
25
			return array( source )
26
27
FORCE_CONTIGUOUS = 1
28
29
30
class ArrayGeometry(object):
31
	"""Vertex-array-based geometry node for faces, lines and points
32
33
	The ArrayGeometry class allows for rendering various
34
	types of geometry using the vertex-array extensions of
35
	OpenGL 1.1 and above.
36
	
37
	The ArrayGeometry is a non-node-object used by the
38
	IndexedFaceSet for rendering an array of triangle
39
	vertices.  Originally it also handled the PointSet
40
	and IndexedLineSet.  The ArrayGeometry object is
41
	cached using the cache module, and regenerated if
42
	the holding object changes field values or is
43
	deleted.
44
	"""
45
	def __init__ (
46
		self,
47
		vertexArray,# array of vertex coordinates to draw
48
		colorArray= None, # optional array of vertex colors
49
		normalArray= None, # optional array of normals
50
		textureCoordinateArray= None, # optional array of texture coordinates
51
		objectType= GL_TRIANGLES, # type of primitive, see glDrawArrays, allowed are:
52
			#GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,
53
			#GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN,	GL_TRIANGLES, GL_QUAD_STRIP,
54
			#GL_QUADS, and GL_POLYGON 
55
		startIndex = 0, # the index from which to draw, see glDrawArrays
56
		count = -1, # by default, render the whole array (len(vertexArray)), see glDrawArrays
57
		ccw = 1, # determines winding direction
58
		solid = 1, # whether backspace culling may be enabled
59
	):
60
		"""Initialize the ArrayGeometry
61
62
		vertexArray -- array of vertex coordinates to draw
63
		colorArray = None -- optional array of vertex colors
64
		normalArray = None -- optional array of normals
65
		textureCoordinateArray = None -- optional array of
66
			texture coordinates
67
		objectType= GL_TRIANGLES -- type of primitive, see
68
			glDrawArrays.  Allowed values are:
69
				GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,
70
				GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN,	GL_TRIANGLES,
71
				GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON
72
			though few of those save points, lines and triangles
73
			have actually been tested.  Only triangles is currently
74
			used.
75
		startIndex = 0 -- the index from which to draw,
76
			see glDrawArrays
77
		count = -1 -- by default, render the whole array
78
			(len(vertexArray)), see glDrawArrays
79
		ccw = 1 -- determines winding direction
80
			see glFrontFace
81
		solid = 1 -- whether backspace culling should be enabled
82
			see glEnable( GL_CULL_FACE )
83
		"""
84
		geometry_log.debug( 'New array geometry node' )
85
		if FORCE_CONTIGUOUS:
86
			if vertexArray is not None and len(vertexArray):
87
				vertexArray = contiguous( vertexArray )
88
			if colorArray  is not None and len(colorArray):
89
				colorArray = contiguous( colorArray )
90
			if normalArray is not None and len(normalArray):
91
				normalArray = contiguous( normalArray )
92
			if textureCoordinateArray is not None and len(textureCoordinateArray):
93
				textureCoordinateArray = contiguous( textureCoordinateArray )
94
		if vbo.get_implementation():
95
			geometry_log.debug( "VBO implementation available" )
96
			if vertexArray is not None and len(vertexArray):
97
				vertexArray = vbo.VBO( vertexArray )
98
			if colorArray is not None and len(colorArray):
99
				colorArray = vbo.VBO( colorArray )
100
			if normalArray is not None and len(normalArray):
101
				normalArray = vbo.VBO( normalArray )
102
			if textureCoordinateArray is not None and len(textureCoordinateArray):
103
				textureCoordinateArray = vbo.VBO( textureCoordinateArray )
104
		if count < 0:
105
			count = len (vertexArray)
106
		self.vertices = vertexArray
107
		self.colours = colorArray
108
		self.normals = normalArray
109
		self.textures = textureCoordinateArray
110
		self.arguments = (objectType, startIndex,count)
111
		geometry_log.debug( '  array geometry: %s, %s', self.arguments, len(self.vertices) )
112
		if ccw:
113
			self.ccw = GL_CCW
114
		else:
115
			self.ccw = GL_CW
116
		self.solid = solid
117
	def callBound( self, function, array ):
118
		if hasattr( array, 'bind' ):
119
			array.bind()
120
			try:
121
				return function(array)
122
			finally:
123
				array.unbind()
124
		else:
125
			return function(array)
126
	def render (
127
			self,
128
			visible = 1, # can skip normals and textures if not
129
			lit = 1, # can skip normals if not
130
			textured = 1, # can skip textureCoordinates if not
131
			transparent = 0, # need to sort triangle geometry...
132
			mode = None, # the renderpass object for which we compile
133
		):
134
		"""Render the ArrayGeometry object
135
136
		called by IndexedFaceSet.render to do the actual
137
		rendering of the node.
138
		"""
139
		if not len(self.vertices):
140
			return 1 # we are already finished
141
		vboAvailable = bool(vbo.get_implementation())
142
		glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
143
		glPushAttrib(GL_ALL_ATTRIB_BITS)
144
		try:
145
			glEnableClientState( GL_VERTEX_ARRAY )
146 63
			self.callBound( glVertexPointerf, self.vertices)
147 1
			if visible and self.colours is not None:
148
				# make the color field alter the diffuse color, should instead be aware of current material/lighting...
149
				glColorMaterial( GL_FRONT_AND_BACK, GL_DIFFUSE)
150
				glEnable( GL_COLOR_MATERIAL )
151
				glEnableClientState( GL_COLOR_ARRAY )
152 56
				self.callBound( glColorPointerf, self.colours)
153 1
#			else:
154
#				glDisableClientState( GL_COLOR_ARRAY )
155
			if lit and self.normals is not None:
156
				glEnableClientState( GL_NORMAL_ARRAY )
157 56
				self.callBound( glNormalPointerf, self.normals)
158 1
				glEnable(GL_NORMALIZE); # should do this explicitly eventually
159
			else:
160
				glDisable( GL_LIGHTING )
161
#				glDisableClientState( GL_NORMAL_ARRAY )
162
				
163
			if visible and textured and self.textures is not None:
164
				glEnableClientState( GL_TEXTURE_COORD_ARRAY )
165 56
				self.callBound( glTexCoordPointerf, self.textures )
166 1
#			else:
167
#				glDisableClientState( GL_TEXTURE_COORD_ARRAY )
168
			glFrontFace( self.ccw)
169
			if self.solid:# and not transparent:
170
				glEnable( GL_CULL_FACE )
171
			else:
172
				glDisable( GL_CULL_FACE )
173
			# do the actual rendering
174
			if visible and transparent:
175 123
				self.drawTransparent( mode = mode )
176 1
			else:
177
				self.draw()
178
			# cleanup the environment
179
		finally:
180
			glPopAttrib()
181
			glPopClientAttrib()
182
		return 1
183
	def draw( self ):
184
		"""Does the actual rendering after the arrays are set up
185
186
		At the moment, is a simple call to glDrawArrays
187
		"""
188 21
#		geometry_log.debug( 'Drawing array geometry: %s, %s', self.arguments, len(self.vertices) )
189
		glDrawArrays( *self.arguments )
190
#		geometry_log.debug( 'Finished array geometry' )
191 123
	def drawTransparent( self, mode ):
192 1
		"""Same as draw, but called when a transparent render is required
193
194
		This uses triangleutilities and polygonsort to render
195
		the polygons in view-depth-sorted order (back to front).
196
197
		It does not provide for automatically tesselating
198
		intersecting transparent polygons, so there will
199
		be potential rendering artifacts.
200
		"""
201
		if not hasattr( self, 'centers'):
202
			self.centers = triangleutilities.centers( self.vertices )
203
		indices = polygonsort.indices(
204
			polygonsort.distances(
205 123
				self.centers, 
206
				modelView = mode.getModelView(),
207
				projection = mode.getProjection(),
208
				viewport = mode.getViewport(),
209 1
			)
210 17
		).astype( 'I' )
211 1
		objectType = self.arguments[0]
212
		assert objectType == GL_TRIANGLES, """Only triangles are sortable, a non-triangle mesh was told to be transparent!"""
213
		glDrawElementsui(
214
			objectType,
215
			indices
216
		)
217
		

Loggerhead 1.10 is a web-based interface for Bazaar branches