/
indexedlineset.py
194 lines (185 loc) · 7.57 KB
/
indexedlineset.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
"""IndexedLineSet VRML97 node implemented using display-lists"""
from OpenGL.GL import *
from OpenGLContext import displaylist
from OpenGLContext.scenegraph import coordinatebounded
from vrml.vrml97 import basenodes
import warnings
from vrml import protofunctions
try:
from itertools import izip_longest as zip_longest
except ImportError:
from itertools import zip_longest
class IndexedLineSet(
coordinatebounded.CoordinateBounded,
basenodes.IndexedLineSet
):
"""VRML97-style Line-Set object
The IndexedLineSet provides GL_LINE/GL_LINE_STRIP
geometry, with support for per-vertex or whole-set
colors.
http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-IS-VRML97WithAmendment1/part1/nodesRef.html#IndexedLineSet
# This code is not OpenGL 3.1 compatible
"""
def compile( self, mode=None ):
"""Compile the IndexedLineSet into a display-list
"""
if self.coord and len(self.coord.point) and len(self.coordIndex):
dl = displaylist.DisplayList()
holder = mode.cache.holder(self, dl)
for field in protofunctions.getFields( self ):
# change to any field requires a recompile
holder.depend( self, field )
for (n, attr) in [
(self.coord, 'point'),
(self.color, 'color'),
]:
if n:
holder.depend( n, protofunctions.getField(n,attr) )
points = self.coord.point
indices = expandIndices( self.coordIndex )
#XXX should do sanity checks here...
if self.color and len(self.color.color):
colors = self.color.color
if self.colorPerVertex:
if len(self.colorIndex):
colorIndices = expandIndices( self.colorIndex )
else:
colorIndices = indices
else:
if len(self.colorIndex):
# each item represents a single polyline colour
colorIndices = self.colorIndex
else:
# each item in color used in turn by each polyline
colorIndices = range(len(indices))
# compile the color-friendly ILS
dl.start()
try:
glEnable( GL_COLOR_MATERIAL )
for index in range(len(indices)):
polyline = indices[index]
color = colorIndices[index]
try:
color = int(color)
except (TypeError,ValueError):
glBegin( GL_LINE_STRIP )
try:
for i,c in zip_longest(polyline, color):
if c is not None:
# numpy treats None as retrieve all??? why?
currentColor = colors[c]
if currentColor is not None:
glColor3d( *currentColor )
glVertex3f(*points[i])
finally:
glEnd()
else:
glColor3d( *colors[color] )
glBegin( GL_LINE_STRIP )
try:
for i in polyline:
glVertex3f(*points[i])
finally:
glEnd()
glDisable( GL_COLOR_MATERIAL )
finally:
dl.end()
else:
dl.start()
try:
for index in range(len(indices)):
polyline = indices[index]
glBegin( GL_LINE_STRIP )
try:
for i in polyline:
glVertex3f(*points[i])
finally:
glEnd()
finally:
dl.end()
return dl
return None
def render (
self,
visible = 1, # can skip normals and textures if not
lit = 1, # can skip normals if not
textured = 1, # can skip textureCoordinates if not
transparent = 0, # need to sort triangle geometry...
mode = None, # the renderpass object for which we compile
):
"""Render the IndexedFaceSet's geometry for a Shape
visible -- if false, do nothing
lit - ignored
textured -- ignored
transparent -- ignored
"""
if visible:
dl = mode.cache.getData(self)
if not dl:
dl = self.compile(mode=mode)
if dl is None:
return 1
# okay, is now a (cached) display list object
dl()
return 1
def yeildVertices( self ):
"""Yield set of vertices to be rendered..."""
# this is an unfinished start to getting OpenGL 3.1 operation
if self.coord and len(self.coord.point) and len(self.coordIndex):
points = self.coord.point
indices = expandIndices( self.coordIndex )
currentColor = None
#XXX should do sanity checks here...
if self.color and len(self.color.color):
colors = self.color.color
if self.colorPerVertex:
if len(self.colorIndex):
colorIndices = expandIndices( self.colorIndex )
else:
colorIndices = indices
else:
if len(self.colorIndex):
# each item represents a single polyline colour
colorIndices = self.colorIndex
else:
# each item in color used in turn by each polyline
colorIndices = range(len(indices))
# compile the color-friendly ILS
for index in range(len(indices)):
polyline = indices[index]
color = colorIndices[index]
try:
color = int(color)
except (TypeError,ValueError):
for i,c in zip_longest(polyline, color):
if c is not None:
# numpy treats None as retrieve all??? why?
currentColor = colors[c]
yield currentColor, points[i]
else:
for i in polyline:
yield colors[color], points[i]
yield None
else:
for index in range(len(indices)):
polyline = indices[index]
for i in polyline:
yield None, points[i]
yield None
def expandIndices( indices ):
"""Create a set of poly-line definitions"""
items = []
current = []
for i in indices:
if i == -1:
if len(current)<2:
# should warn the user
warnings.warn( """IndexedLineSet Polyline of length < 2""")
else:
items.append( current )
current = []
else:
current.append( i )
if current:
items.append( current )
return items