yapCAD 0.2.5__py2.py3-none-any.whl → 0.3.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yapcad/__init__.py +8 -8
- yapcad/combine.py +83 -371
- yapcad/drawable.py +44 -3
- yapcad/ezdxf_drawable.py +1 -1
- yapcad/geom.py +214 -276
- yapcad/geom3d.py +975 -55
- yapcad/geom3d_util.py +541 -0
- yapcad/geom_util.py +817 -0
- yapcad/geometry.py +442 -50
- yapcad/geometry_checks.py +112 -0
- yapcad/geometry_utils.py +115 -0
- yapcad/io/__init__.py +5 -0
- yapcad/io/stl.py +83 -0
- yapcad/mesh.py +46 -0
- yapcad/metadata.py +109 -0
- yapcad/octtree.py +627 -0
- yapcad/poly.py +153 -299
- yapcad/pyglet_drawable.py +597 -61
- yapcad/triangulator.py +103 -0
- yapcad/xform.py +10 -5
- {yapCAD-0.2.5.dist-info → yapcad-0.3.1.dist-info}/METADATA +110 -39
- yapcad-0.3.1.dist-info/RECORD +27 -0
- {yapCAD-0.2.5.dist-info → yapcad-0.3.1.dist-info}/WHEEL +1 -1
- yapCAD-0.2.5.dist-info/RECORD +0 -17
- {yapCAD-0.2.5.dist-info → yapcad-0.3.1.dist-info/licenses}/AUTHORS.rst +0 -0
- {yapCAD-0.2.5.dist-info → yapcad-0.3.1.dist-info/licenses}/LICENSE +0 -0
- {yapCAD-0.2.5.dist-info → yapcad-0.3.1.dist-info/licenses}/LICENSE.txt +0 -0
- {yapCAD-0.2.5.dist-info → yapcad-0.3.1.dist-info}/top_level.txt +0 -0
yapcad/pyglet_drawable.py
CHANGED
@@ -31,6 +31,7 @@ import pyglet.gl as gl
|
|
31
31
|
import pyglet.graphics as graphics
|
32
32
|
|
33
33
|
from yapcad.geom import *
|
34
|
+
from yapcad.geom3d import *
|
34
35
|
import yapcad.drawable as drawable
|
35
36
|
|
36
37
|
## openGL utility functions
|
@@ -53,8 +54,322 @@ yapCAD_legend="""
|
|
53
54
|
</font>
|
54
55
|
"""
|
55
56
|
|
57
|
+
class Material():
|
58
|
+
"""
|
59
|
+
Representation of an OpenGL-style material
|
60
|
+
"""
|
61
|
+
|
62
|
+
def __repr__(self):
|
63
|
+
return f"Material(ambient={self.ambient}, diffuse={self.diffuse}, specular={self.specular}, emission={self.emission}, shininess={self.shininess}, desc=\"{self.desc}\")"
|
64
|
+
|
65
|
+
def __checkargs(self,v):
|
66
|
+
if ( not (len(v) == 3 or len(v) == 4) or
|
67
|
+
len(list(filter(lambda x: not isinstance(x,(int,float)),v))) > 0 or
|
68
|
+
len(list(filter(lambda x: x < 0.0 or x > 1.0,v))) > 0):
|
69
|
+
raise ValueError('bad arguments to property setter')
|
70
|
+
if len(v) == 3:
|
71
|
+
return [v[0],v[1],v[2],1.0]
|
72
|
+
else:
|
73
|
+
return v
|
74
|
+
|
75
|
+
|
76
|
+
def __init__(self,**kwargs):
|
77
|
+
self.__ambient = vec(0.2, 0.2, 0.2, 1.0)
|
78
|
+
self.__diffuse = vec(0.5, 0.5, 0.5, 1.0)
|
79
|
+
self.__specular = vec(0.5, 0.5, 0.5, 1.0)
|
80
|
+
self.__emission = vec(0.0, 0.0, 0.0, 1.0)
|
81
|
+
self.__shininess = 50
|
82
|
+
self.__desc = ""
|
83
|
+
if 'ambient' in kwargs:
|
84
|
+
self.ambient = kwargs['ambient']
|
85
|
+
if 'diffuse' in kwargs:
|
86
|
+
self.diffuse = kwargs['diffuse']
|
87
|
+
if 'specular' in kwargs:
|
88
|
+
self.specular = kwargs['specular']
|
89
|
+
if 'emission' in kwargs:
|
90
|
+
self.emission = kwargs['emission']
|
91
|
+
if 'shininess' in kwargs:
|
92
|
+
self.shininess = kwargs['shininess']
|
93
|
+
if 'desc' in kwargs:
|
94
|
+
self.desc = kwargs['desc']
|
95
|
+
|
96
|
+
@property
|
97
|
+
def ambient(self):
|
98
|
+
return list(self.__ambient)
|
99
|
+
|
100
|
+
@ambient.setter
|
101
|
+
def ambient(self,*v):
|
102
|
+
if len(v) == 1:
|
103
|
+
v = v[0]
|
104
|
+
v = self.__checkargs(v)
|
105
|
+
self.__ambient = vec(*v)
|
106
|
+
|
107
|
+
@property
|
108
|
+
def diffuse(self):
|
109
|
+
return list(self.__diffuse)
|
110
|
+
|
111
|
+
@diffuse.setter
|
112
|
+
def diffuse(self,*v):
|
113
|
+
if len(v) == 1:
|
114
|
+
v = v[0]
|
115
|
+
v = self.__checkargs(v)
|
116
|
+
self.__diffuse = vec(*v)
|
117
|
+
|
118
|
+
@property
|
119
|
+
def specular(self):
|
120
|
+
return list(self.__specular)
|
121
|
+
|
122
|
+
@specular.setter
|
123
|
+
def specular(self,*v):
|
124
|
+
if len(v) == 1:
|
125
|
+
v = v[0]
|
126
|
+
v = self.__checkargs(v)
|
127
|
+
self.__specular = vec(*v)
|
128
|
+
|
129
|
+
@property
|
130
|
+
def emission(self):
|
131
|
+
return list(self.__emission)
|
132
|
+
|
133
|
+
@emission.setter
|
134
|
+
def emission(self,*v):
|
135
|
+
if len(v) == 1:
|
136
|
+
v = v[0]
|
137
|
+
v = self.__checkargs(v)
|
138
|
+
self.__emission = vec(*v)
|
139
|
+
|
140
|
+
@property
|
141
|
+
def shininess(self):
|
142
|
+
return self.__shininess
|
143
|
+
|
144
|
+
@shininess.setter
|
145
|
+
def shininess(self,v):
|
146
|
+
if not isinstance(v,(int,float)) or v < 0 or v > 128:
|
147
|
+
raise ValueError('bad shininess')
|
148
|
+
self.__shininess=v
|
149
|
+
|
150
|
+
@property
|
151
|
+
def desc(self):
|
152
|
+
return self.__desc
|
153
|
+
|
154
|
+
@desc.setter
|
155
|
+
def desc(self,v):
|
156
|
+
if not isinstance(v,str):
|
157
|
+
raise ValueError('bad description')
|
158
|
+
self.__desc = v
|
159
|
+
|
160
|
+
@property
|
161
|
+
def material(self):
|
162
|
+
return pyglet.model.Material(self.desc,
|
163
|
+
self.diffuse,
|
164
|
+
self.ambient,
|
165
|
+
self.specular,
|
166
|
+
self.emission,
|
167
|
+
self.shininess)
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
## global materials dictionary
|
172
|
+
materials = {}
|
173
|
+
|
174
|
+
materials['default'] = Material(ambient=[0.5, 0.3, 0.2, 1.0],
|
175
|
+
diffuse = [0.6, 0.5, 0.3, 1.0],
|
176
|
+
specular = [1.0, 0.8, 0.5, 1.0],
|
177
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
178
|
+
shininess = 20,
|
179
|
+
desc = "default material, dull gold")
|
180
|
+
|
181
|
+
|
182
|
+
materials['groundplane'] = Material(diffuse = [0.02, 0.02, 0.023, 1.0],
|
183
|
+
ambient = [0.01, 0.01, 0.02, 1.0],
|
184
|
+
specular = [0.05, 0.06, 0.08, 1.0],
|
185
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
186
|
+
shininess = 20,
|
187
|
+
desc = "ground plane material")
|
188
|
+
|
189
|
+
## The following materials a from tables published at
|
190
|
+
## http://devernay.free.fr/cours/opengl/materials.html and
|
191
|
+
## http://www.it.hiof.no/~borres/j3d/explain/light/p-materials.html
|
192
|
+
|
193
|
+
materials['emerald'] = Material(ambient=[0.0215, 0.1745, 0.0215, 1.0],
|
194
|
+
diffuse=[0.07568, 0.61424, 0.07568, 1.0],
|
195
|
+
specular=[0.633, 0.727811, 0.633, 1.0],
|
196
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
197
|
+
shininess = 0.6*128,
|
198
|
+
desc= "emerald")
|
199
|
+
|
200
|
+
materials['jade'] = Material(ambient=[0.135, 0.2225, 0.1575, 1.0],
|
201
|
+
diffuse=[0.54, 0.89, 0.63, 1.0],
|
202
|
+
specular=[0.316228, 0.316228, 0.316228, 1.0],
|
203
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
204
|
+
shininess = 0.1*128)
|
205
|
+
|
206
|
+
materials['obsidian'] = Material(ambient=[0.05375, 0.05, 0.06625, 1.0],
|
207
|
+
diffuse=[0.18275, 0.17, 0.22525, 1.0],
|
208
|
+
specular=[0.332741, 0.328634, 0.346435, 1.0],
|
209
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
210
|
+
shininess = 0.3*128)
|
211
|
+
|
212
|
+
materials['pearl'] = Material(ambient=[0.25, 0.20725, 0.20725, 1.0],
|
213
|
+
diffuse=[0.9999, 0.829, 0.829, 1.0],
|
214
|
+
specular=[0.296648, 0.296648, 0.296648, 1.0],
|
215
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
216
|
+
shininess = 0.088*128)
|
217
|
+
|
218
|
+
materials['ruby'] = Material(ambient=[0.1745, 0.01175, 0.01175, 1.0],
|
219
|
+
diffuse=[0.61424, 0.04136, 0.04136, 1.0],
|
220
|
+
specular=[0.727811, 0.626959, 0.626959, 1.0],
|
221
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
222
|
+
shininess = 0.6*128)
|
223
|
+
|
224
|
+
materials['turquoise'] = Material(ambient=[0.1, 0.18725, 0.1745, 1.0],
|
225
|
+
diffuse=[0.396, 0.74151, 0.69102, 1.0],
|
226
|
+
specular=[0.297254, 0.30829, 0.306678, 1.0],
|
227
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
228
|
+
shininess = 0.1*128)
|
229
|
+
|
230
|
+
materials['brass'] = Material(ambient=[0.329412, 0.223529, 0.027451, 1.0],
|
231
|
+
diffuse=[0.780392, 0.568627, 0.113725, 1.0],
|
232
|
+
specular=[0.992157, 0.941176, 0.807843, 1.0],
|
233
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
234
|
+
shininess = 0.21794872*128)
|
235
|
+
|
236
|
+
materials['bronze'] = Material(ambient=[0.2125, 0.1275, 0.054, 1.0],
|
237
|
+
diffuse=[0.714, 0.4284, 0.18144, 1.0],
|
238
|
+
specular=[0.393548, 0.271906, 0.166721, 1.0],
|
239
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
240
|
+
shininess = 0.2*128)
|
241
|
+
|
242
|
+
materials['polished bronze'] = Material(
|
243
|
+
ambient =[0.25, 0.148, 0.06475, 1.0],
|
244
|
+
diffuse =[0.4, 0.2368, 0.1036, 1.0],
|
245
|
+
specular =[0.774597, 0.458561, 0.200621, 1.0],
|
246
|
+
shininess =76.8)
|
247
|
+
|
248
|
+
materials['chrome'] = Material(ambient=[0.25, 0.25, 0.25, 1.0],
|
249
|
+
diffuse=[0.4, 0.4, 0.4, 1.0],
|
250
|
+
specular=[0.774597, 0.774597, 0.774597, 1.0],
|
251
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
252
|
+
shininess = 0.6*128)
|
253
|
+
|
254
|
+
materials['copper'] = Material(ambient=[0.19125, 0.0735, 0.0225, 1.0],
|
255
|
+
diffuse=[0.7038, 0.27048, 0.0828, 1.0],
|
256
|
+
specular=[0.256777, 0.137622, 0.086014, 1.0],
|
257
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
258
|
+
shininess = 0.1*128)
|
259
|
+
|
260
|
+
materials['polished copper'] = Material(
|
261
|
+
ambient =[ 0.2295, 0.08825, 0.0275, 1.0 ],
|
262
|
+
diffuse =[0.5508, 0.2118, 0.066, 1.0 ],
|
263
|
+
specular =[0.580594, 0.223257, 0.0695701, 1.0 ],
|
264
|
+
shininess =51.2)
|
265
|
+
|
266
|
+
materials['gold'] = Material( ambient=[0.24725, 0.1995, 0.0745, 1.0],
|
267
|
+
diffuse=[0.75164, 0.60648, 0.22648, 1.0],
|
268
|
+
specular=[0.628281, 0.555802, 0.366065, 1.0],
|
269
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
270
|
+
shininess = 0.4*128)
|
271
|
+
|
272
|
+
materials['polished gold'] = Material(
|
273
|
+
ambient =[ 0.24725, 0.2245, 0.0645, 1.0 ],
|
274
|
+
diffuse =[0.34615, 0.3143, 0.0903, 1.0 ],
|
275
|
+
specular =[ 0.797357, 0.723991, 0.208006, 1.0],
|
276
|
+
shininess =83.2)
|
277
|
+
|
278
|
+
materials['tin'] = Material(
|
279
|
+
ambient =[ 0.105882, 0.058824, 0.113725, 1.0 ],
|
280
|
+
diffuse =[0.427451, 0.470588, 0.541176, 1.0 ],
|
281
|
+
specular =[0.333333, 0.333333, 0.521569, 1.0 ],
|
282
|
+
shininess = 9.84615)
|
283
|
+
|
284
|
+
materials['silver'] = Material(
|
285
|
+
ambient=[0.19225, 0.19225, 0.19225, 1.0],
|
286
|
+
diffuse=[0.50754, 0.50754, 0.50754, 1.0],
|
287
|
+
specular=[0.508273, 0.508273, 0.508273, 1.0],
|
288
|
+
emission = [0.0, 0.0, 0.0, 1.0],
|
289
|
+
shininess = 0.4*128)
|
290
|
+
|
291
|
+
materials['polished silver'] = Material(
|
292
|
+
ambient =[ 0.23125, 0.23125, 0.23125, 1.0 ],
|
293
|
+
diffuse =[0.2775, 0.2775, 0.2775, 1.0 ],
|
294
|
+
specular =[0.773911, 0.773911, 0.773911, 1.0 ],
|
295
|
+
shininess =89.6)
|
296
|
+
|
297
|
+
materials['black plastic'] = Material(ambient=[0.0, 0.0, 0.0, 1.0],
|
298
|
+
diffuse=[0.01, 0.01, 0.01, 1.0],
|
299
|
+
specular=[0.50, 0.50, 0.50, 1.0],
|
300
|
+
shininess=.25*128)
|
301
|
+
|
302
|
+
materials['cyan plastic'] = Material(ambient=[0.0, 0.1, 0.06, 1.0],
|
303
|
+
diffuse=[0.0, 0.50980392, 0.50980392, 1.0],
|
304
|
+
specular=[0.50196078, 0.50196078,
|
305
|
+
0.50196078, 1.0],
|
306
|
+
shininess=.25*128)
|
307
|
+
|
308
|
+
materials['green plastic'] = Material(ambient=[0.0, 0.0, 0.0, 1.0],
|
309
|
+
diffuse=[0.1, 0.35, 0.1, 1.0],
|
310
|
+
specular=[0.45, 0.55, 0.45, 1.0],
|
311
|
+
shininess=.25*128)
|
312
|
+
|
313
|
+
materials['red plastic'] = Material(ambient=[0.0, 0.0, 0.0, 1.0],
|
314
|
+
diffuse=[0.5, 0.0, 0.0, 1.0],
|
315
|
+
specular=[0.7, 0.6, 0.6, 1.0],
|
316
|
+
emission=[0.0, 0.0, 0.0, 1.0],
|
317
|
+
shininess=.25*128)
|
318
|
+
|
319
|
+
materials['white plastic'] = Material(ambient=[0.0, 0.0, 0.0, 1.0],
|
320
|
+
diffuse=[0.55, 0.55, 0.55, 1.0],
|
321
|
+
specular=[0.70, 0.70, 0.70, 1.0],
|
322
|
+
shininess=.25*128)
|
323
|
+
|
324
|
+
materials['yellow plastic'] = Material(ambient=[0.0, 0.0, 0.0, 1.0],
|
325
|
+
diffuse=[0.5, 0.5, 0.0, 1.0],
|
326
|
+
specular=[0.60, 0.60, 0.50, 1.0],
|
327
|
+
shininess=.25*128)
|
328
|
+
|
329
|
+
materials['black rubber'] = Material(ambient=[0.02, 0.02, 0.02, 1.0],
|
330
|
+
diffuse=[0.01, 0.01, 0.01, 1.0],
|
331
|
+
specular=[0.4, 0.4, 0.4, 1.0],
|
332
|
+
emission=[0.0, 0.0, 0.0, 1.0],
|
333
|
+
shininess=.078125*128)
|
334
|
+
|
335
|
+
materials['cyan rubber'] = Material(ambient=[0.0, 0.05, 0.05, 1.0],
|
336
|
+
diffuse=[0.4, 0.5, 0.5, 1.0],
|
337
|
+
specular=[0.04, 0.7, 0.7, 1.0],
|
338
|
+
emission=[0.0, 0.0, 0.0, 1.0],
|
339
|
+
shininess=.078125*128)
|
340
|
+
|
341
|
+
materials['green rubber'] = Material(ambient=[0.0, 0.05, 0.0, 1.0],
|
342
|
+
diffuse=[0.4, 0.5, 0.4, 1.0],
|
343
|
+
specular=[0.04, 0.7, 0.04, 1.0],
|
344
|
+
shininess=.078125*128)
|
345
|
+
|
346
|
+
materials['red rubber'] = Material(ambient=[0.05, 0.0, 0.0, 1.0],
|
347
|
+
diffuse=[0.5, 0.4, 0.4, 1.0],
|
348
|
+
specular=[0.7, 0.04, 0.04, 1.0],
|
349
|
+
shininess=.078125*128)
|
350
|
+
|
351
|
+
materials['white rubber'] = Material(ambient=[0.05, 0.05, 0.05, 1.0],
|
352
|
+
diffuse=[0.5, 0.5, 0.5, 1.0],
|
353
|
+
specular=[0.7, 0.7, 0.7, 1.0],
|
354
|
+
emission=[0.0, 0.0, 0.0, 1.0],
|
355
|
+
shininess=.078125*128)
|
356
|
+
|
357
|
+
materials['yellow rubber'] = Material(ambient=[0.05, 0.05, 0.0, 1.0],
|
358
|
+
diffuse=[0.5, 0.5, 0.4, 1.0],
|
359
|
+
specular=[0.7, 0.7, 0.04, 1.0],
|
360
|
+
shininess=.078125*128)
|
361
|
+
|
362
|
+
|
363
|
+
## "throwaway" class for keeping track of object stuff
|
364
|
+
class GeomObject:
|
365
|
+
pass
|
366
|
+
|
367
|
+
|
56
368
|
## class to provide openGL drawing functionality
|
57
369
|
class pygletDraw(drawable.Drawable):
|
370
|
+
"""
|
371
|
+
yapCAD ``drawable`` subclass for OpenGL rendering with pyglet
|
372
|
+
"""
|
58
373
|
|
59
374
|
def window(self):
|
60
375
|
window = []
|
@@ -66,6 +381,7 @@ class pygletDraw(drawable.Drawable):
|
|
66
381
|
except pyglet.window.NoSuchConfigException:
|
67
382
|
# Fall back to no multisampling for old hardware
|
68
383
|
window = pyglet.window.Window(resizable=True)
|
384
|
+
self.__fps_display = pyglet.window.FPSDisplay(window)
|
69
385
|
return window
|
70
386
|
|
71
387
|
|
@@ -84,24 +400,51 @@ class pygletDraw(drawable.Drawable):
|
|
84
400
|
gl.glLightfv(gl.GL_LIGHT1, gl.GL_DIFFUSE, vec(0.8, 0.8, 0.8, 1))
|
85
401
|
gl.glLightfv(gl.GL_LIGHT1, gl.GL_POSITION, vec(-10.0, -20.0, 20.0, 0))
|
86
402
|
|
87
|
-
# Create a
|
88
|
-
|
89
|
-
ambient = [0.5, 0.5, 0.3, 1.0]
|
90
|
-
specular = [1.0, 1.0, 1.0, 1.0]
|
91
|
-
emission = [0.0, 0.0, 0.0, 1.0]
|
92
|
-
shininess = 50
|
93
|
-
material = pyglet.model.Material("", diffuse, ambient, specular, emission, shininess)
|
403
|
+
# Create a default material and Group for the Model
|
404
|
+
material = materials['default'].material
|
94
405
|
self.group = pyglet.model.MaterialGroup(material=material)
|
95
406
|
|
96
407
|
# Create a Material and Group for the ground plane
|
97
|
-
|
98
|
-
ambient = [0.01, 0.01, 0.01, 1.0]
|
99
|
-
specular = [0.05, 0.05, 0.07, 1.0]
|
100
|
-
emission = [0.0, 0.0, 0.0, 1.0]
|
101
|
-
shininess = 10
|
102
|
-
material2 = pyglet.model.Material("ground", diffuse, ambient, specular, emission, shininess)
|
408
|
+
material2 = materials['groundplane'].material
|
103
409
|
self.group2 = pyglet.model.MaterialGroup(material=material2)
|
104
410
|
|
411
|
+
## utility funtion to update bounding box based on a list of points
|
412
|
+
def upbb(self,pp,box,offset=[0,0,0,1]):
|
413
|
+
epsP = point(epsilon,epsilon,epsilon)
|
414
|
+
epsM = point(-epsilon,-epsilon,-epsilon)
|
415
|
+
for p in pp:
|
416
|
+
p = add(p,offset)
|
417
|
+
if box:
|
418
|
+
box = [ [min(box[0][0],p[0]),min(box[0][1],p[1]),min(box[0][2],p[2])],
|
419
|
+
[max(box[1][0],p[0]),max(box[1][1],p[1]),max(box[1][2],p[2])] ]
|
420
|
+
else:
|
421
|
+
box = [ add(p,epsM),add(p,epsP) ]
|
422
|
+
return box
|
423
|
+
|
424
|
+
|
425
|
+
def addSurface(self,s,batch,group,offset,bbx):
|
426
|
+
assert s[0] == 'surface'
|
427
|
+
vert = s[1]
|
428
|
+
norm = s[2]
|
429
|
+
ind = s[3]
|
430
|
+
pp = []
|
431
|
+
ln = int(len(vert)/3)
|
432
|
+
for i in range(ln):
|
433
|
+
pp.append(vert[i*3:(i+1)*3])
|
434
|
+
bbx = self.upbb(pp,bbx,offset)
|
435
|
+
batch.add_indexed(int(len(vert)/3),
|
436
|
+
gl.GL_TRIANGLES,
|
437
|
+
group,
|
438
|
+
ind,
|
439
|
+
('v3f/static', vert),
|
440
|
+
('n3f/static', norm))
|
441
|
+
return bbx
|
442
|
+
|
443
|
+
__immediate = {}
|
444
|
+
|
445
|
+
def register_immediate(self,func):
|
446
|
+
""" register a function for immediate-mode drawing"""
|
447
|
+
self.__immediate[func.__name__] = func
|
105
448
|
|
106
449
|
def makeBatches(self):
|
107
450
|
# convert geometry lists to overall bounding box and
|
@@ -109,29 +452,17 @@ class pygletDraw(drawable.Drawable):
|
|
109
452
|
|
110
453
|
bbx = False
|
111
454
|
# values for adding small offset to a point to make single-point bounding box
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
for p in pp:
|
118
|
-
if box:
|
119
|
-
box = [ [min(box[0][0],p[0]),min(box[0][1],p[1]),min(box[0][2],p[2])],
|
120
|
-
[max(box[1][0],p[0]),max(box[1][1],p[1]),max(box[1][2],p[2])] ]
|
121
|
-
else:
|
122
|
-
box = [ add(p,epsM),add(p,epsP) ]
|
123
|
-
return box
|
124
|
-
|
125
|
-
if self.__points == [] and \
|
126
|
-
self.__lines == [] and \
|
127
|
-
self.__linestrips == [] and \
|
128
|
-
self.__surfaces == []:
|
455
|
+
if ( self.__points == [] and
|
456
|
+
self.__lines == [] and
|
457
|
+
self.__linestrips == [] and
|
458
|
+
len(self.__objectdict) == 0 and
|
459
|
+
self.__surfaces == [] ):
|
129
460
|
raise ValueError('nothing to render')
|
130
461
|
|
131
462
|
for p in self.__points:
|
132
463
|
pp = p[0]
|
133
464
|
pc = p[1]
|
134
|
-
bbx = upbb(pp[1],bbx)
|
465
|
+
bbx = self.upbb(pp[1],bbx)
|
135
466
|
self.__batch1.add(int(len(pp[1])/3),gl.GL_POINTS,self.group,pp,pc)
|
136
467
|
|
137
468
|
for l in self.__lines:
|
@@ -139,7 +470,7 @@ class pygletDraw(drawable.Drawable):
|
|
139
470
|
lc = l[1]
|
140
471
|
pp = [list(ll[1][0:3])]
|
141
472
|
pp.append(list(ll[1][3:6]))
|
142
|
-
bbx = upbb(pp,bbx)
|
473
|
+
bbx = self.upbb(pp,bbx)
|
143
474
|
self.__batch1.add(int(len(ll[1])/3),gl.GL_LINES,self.group,ll,lc)
|
144
475
|
|
145
476
|
for l in self.__linestrips:
|
@@ -150,27 +481,66 @@ class pygletDraw(drawable.Drawable):
|
|
150
481
|
ln = int(len(ll[1])/3)
|
151
482
|
for i in range(ln):
|
152
483
|
pp.append(ll[1][i*3:(i+1)*3])
|
153
|
-
bbx =upbb(pp,bbx)
|
484
|
+
bbx =self.upbb(pp,bbx)
|
154
485
|
self.__batch1.add_indexed(int(len(ll[1])/3),
|
155
486
|
gl.GL_LINES,
|
156
487
|
self.group,
|
157
488
|
li,ll,lc)
|
158
489
|
|
490
|
+
|
491
|
+
|
492
|
+
def lineSurface(s,obj):
|
493
|
+
assert s[0] == 'surface'
|
494
|
+
vert = s[1]
|
495
|
+
ind = s[3]
|
496
|
+
drawn = []
|
497
|
+
for j in range(0,len(ind),3):
|
498
|
+
i = ind[j:(j+3)]
|
499
|
+
l1 = i[0],i[1]
|
500
|
+
if l1[0] > l1[1]:
|
501
|
+
l1 = i[1],i[0]
|
502
|
+
l2 = i[1],i[2]
|
503
|
+
if l2[0] > l2[1]:
|
504
|
+
l2 = i[2],i[1]
|
505
|
+
l3 = i[2],i[0]
|
506
|
+
if l3[0] > l3[1]:
|
507
|
+
l3 = i[0],i[2]
|
508
|
+
if not l1 in drawn:
|
509
|
+
self.draw_line(vert[l1[0]*3:l1[0]*3+3],
|
510
|
+
vert[l1[1]*3:l1[1]*3+3],
|
511
|
+
entity=obj)
|
512
|
+
drawn.append(l1)
|
513
|
+
if not l2 in drawn:
|
514
|
+
self.draw_line(vert[l2[0]*3:l2[0]*3+3],
|
515
|
+
vert[l2[1]*3:l2[1]*3+3],
|
516
|
+
entity=obj)
|
517
|
+
drawn.append(l2)
|
518
|
+
if not l3 in drawn:
|
519
|
+
self.draw_line(vert[l3[0]*3:l3[0]*3+3],
|
520
|
+
vert[l3[1]*3:l3[1]*3+3],
|
521
|
+
entity=obj)
|
522
|
+
drawn.append(l3)
|
523
|
+
for l in obj.lines:
|
524
|
+
ll = l[0]
|
525
|
+
lc = l[1]
|
526
|
+
obj.linebatch.add(2,gl.GL_LINES,self.group,ll,lc)
|
527
|
+
|
528
|
+
|
529
|
+
for o in self.__objectdict.values():
|
530
|
+
for s in o.surfaces:
|
531
|
+
bbx = self.addSurface(s,o.batch,o.group,
|
532
|
+
point(o.x,o.y,o.z),bbx)
|
533
|
+
lineSurface(s,o)
|
534
|
+
for l in o.lines:
|
535
|
+
ll = l[0]
|
536
|
+
lc = l[1]
|
537
|
+
o.linebatch.add(2,gl.GL_LINES,self.group,ll,lc)
|
538
|
+
|
539
|
+
|
540
|
+
|
159
541
|
for s in self.__surfaces:
|
160
|
-
|
161
|
-
|
162
|
-
ind = s[2]
|
163
|
-
pp = []
|
164
|
-
ln = int(len(vert)/3)
|
165
|
-
for i in range(ln):
|
166
|
-
pp.append(vert[i*3:(i+1)*3])
|
167
|
-
bbx = upbb(pp,bbx)
|
168
|
-
self.__batch2.add_indexed(int(len(vert)/3),
|
169
|
-
gl.GL_TRIANGLES,
|
170
|
-
self.group,
|
171
|
-
ind,
|
172
|
-
('v3f/static', vert),
|
173
|
-
('n3f/static', norm))
|
542
|
+
bbx = self.addSurface(s,self.__batch2,self.group,
|
543
|
+
point(0,0,0),bbx)
|
174
544
|
|
175
545
|
## Create a ground plane
|
176
546
|
self.__batch3.add_indexed(4,
|
@@ -202,23 +572,30 @@ class pygletDraw(drawable.Drawable):
|
|
202
572
|
self.layerlist = [False, '0','PATHS','DRILLS','DOCUMENTATION']
|
203
573
|
|
204
574
|
def on_key_press(symbol,modifiers):
|
575
|
+
handled = False
|
205
576
|
if symbol == pyglet.window.key.UP:
|
577
|
+
handled = True
|
206
578
|
self.__cameradist *= 1.1
|
207
579
|
if self.__cameradist > self.__maxcameradist:
|
208
580
|
self.__cameradist = self.__maxcameradist
|
209
581
|
elif symbol == pyglet.window.key.DOWN:
|
582
|
+
handled = True
|
210
583
|
self.__cameradist *= .90909090
|
211
584
|
if self.__cameradist < self.__mincameradist:
|
212
585
|
self.__cameradist = self.__mincameradist
|
213
586
|
elif symbol == pyglet.window.key.RETURN:
|
587
|
+
handled = True
|
214
588
|
self.__cameradist = self.camerastartdist
|
215
589
|
self.__rx = 0
|
216
590
|
self.__ry = 0
|
217
591
|
elif symbol == pyglet.window.key.P:
|
592
|
+
handled = True
|
218
593
|
self.__drawground = not self.__drawground
|
219
594
|
elif symbol == pyglet.window.key.M:
|
595
|
+
handled = True
|
220
596
|
self.__legend = not self.__legend
|
221
597
|
elif symbol == pyglet.window.key.L:
|
598
|
+
handled = True
|
222
599
|
if not (self.__light0 or self.__light1):
|
223
600
|
self.__light0 = True
|
224
601
|
gl.glEnable(gl.GL_LIGHT0)
|
@@ -229,6 +606,10 @@ class pygletDraw(drawable.Drawable):
|
|
229
606
|
gl.glEnable(gl.GL_LIGHT1)
|
230
607
|
elif self.__light0 and self.__light1:
|
231
608
|
self.__light0 = self.__light1 = False
|
609
|
+
if handled:
|
610
|
+
return pyglet.event.EVENT_HANDLED
|
611
|
+
else:
|
612
|
+
return
|
232
613
|
|
233
614
|
|
234
615
|
self.__window = self.window()
|
@@ -241,7 +622,7 @@ class pygletDraw(drawable.Drawable):
|
|
241
622
|
self.__cameradist = self.camerastartdist = 100.0
|
242
623
|
self.__maxcameradist = 900.0
|
243
624
|
self.__mincameradist = 10.0
|
244
|
-
self.__light0 =
|
625
|
+
self.__light0 = True
|
245
626
|
self.__light1 = False
|
246
627
|
self.__legend = True
|
247
628
|
self.__drawground = True
|
@@ -253,8 +634,9 @@ class pygletDraw(drawable.Drawable):
|
|
253
634
|
self.__surfaces=[]
|
254
635
|
self.__labels = []
|
255
636
|
self.__batch1 = graphics.Batch() # use for lines, points, etc.
|
256
|
-
self.__batch2 = graphics.Batch() # use for surfaces
|
637
|
+
self.__batch2 = graphics.Batch() # default, use for surfaces
|
257
638
|
self.__batch3 = graphics.Batch() # use for environmental features, e.g. ground plane
|
639
|
+
self.__objectdict = {} # use for animated objects
|
258
640
|
self.__bbox = False
|
259
641
|
|
260
642
|
@self.__window.event
|
@@ -263,8 +645,6 @@ class pygletDraw(drawable.Drawable):
|
|
263
645
|
self.__ry -= dy
|
264
646
|
return pyglet.event.EVENT_HANDLED
|
265
647
|
|
266
|
-
|
267
|
-
|
268
648
|
@self.__window.event
|
269
649
|
def on_draw():
|
270
650
|
self.__window.clear()
|
@@ -276,6 +656,8 @@ class pygletDraw(drawable.Drawable):
|
|
276
656
|
|
277
657
|
#gl.glMatrixMode(gl.GL_MODELVIEW)
|
278
658
|
gl.glLoadIdentity()
|
659
|
+
if not self.__bbox:
|
660
|
+
self.__bbox =[point(-1,-1,-1),point(1,1,1)]
|
279
661
|
cent = scale3(add(self.__bbox[0],self.__bbox[1]),0.5)
|
280
662
|
rnge = sub(self.__bbox[1],self.__bbox[0])
|
281
663
|
mdim = max(rnge)
|
@@ -299,6 +681,25 @@ class pygletDraw(drawable.Drawable):
|
|
299
681
|
gl.glEnable(gl.GL_LIGHTING)
|
300
682
|
self.__batch2.draw()
|
301
683
|
|
684
|
+
# execute any immediate-mode registered rendering functions
|
685
|
+
for f in self.__immediate.values():
|
686
|
+
f()
|
687
|
+
|
688
|
+
for obj in self.__objectdict.values():
|
689
|
+
gl.glMatrixMode(gl.GL_MODELVIEW)
|
690
|
+
gl.glPushMatrix()
|
691
|
+
gl.glTranslatef(obj.x,obj.y,obj.z)
|
692
|
+
gl.glRotatef(obj.rx, 1, 0, 0)
|
693
|
+
gl.glRotatef(obj.ry, 0, 1, 0)
|
694
|
+
gl.glRotatef(obj.rz, 0, 0, 1)
|
695
|
+
if obj.lighting and (self.__light0 or self.__light1):
|
696
|
+
gl.glEnable(gl.GL_LIGHTING)
|
697
|
+
obj.batch.draw()
|
698
|
+
else:
|
699
|
+
gl.glDisable(gl.GL_LIGHTING)
|
700
|
+
obj.linebatch.draw()
|
701
|
+
gl.glPopMatrix()
|
702
|
+
|
302
703
|
#gl.glDisable(gl.GL_BLEND)
|
303
704
|
gl.glDisable(gl.GL_LIGHTING)
|
304
705
|
gl.glColor3f(1., 1., 1.)
|
@@ -308,7 +709,7 @@ class pygletDraw(drawable.Drawable):
|
|
308
709
|
gl.glTranslatef(0,0,label[1])
|
309
710
|
label[0].draw()
|
310
711
|
gl.glPopMatrix()
|
311
|
-
|
712
|
+
|
312
713
|
if self.__legend:
|
313
714
|
gl.glMatrixMode(gl.GL_MODELVIEW)
|
314
715
|
gl.glPushMatrix()
|
@@ -324,6 +725,7 @@ class pygletDraw(drawable.Drawable):
|
|
324
725
|
width=400,
|
325
726
|
multiline=True)
|
326
727
|
label.draw()
|
728
|
+
self.__fps_display.draw()
|
327
729
|
gl.glMatrixMode(gl.GL_PROJECTION)
|
328
730
|
gl.glPopMatrix()
|
329
731
|
gl.glMatrixMode(gl.GL_MODELVIEW)
|
@@ -371,6 +773,31 @@ class pygletDraw(drawable.Drawable):
|
|
371
773
|
dist = self.__mincameradist
|
372
774
|
self._set_cameradist(dist)
|
373
775
|
|
776
|
+
|
777
|
+
@property
|
778
|
+
def rx(self):
|
779
|
+
return self.__rx
|
780
|
+
|
781
|
+
@rx.setter
|
782
|
+
def rx(self,v):
|
783
|
+
if not isinstance(v,(int,float)):
|
784
|
+
raise ValueError('invalid camera rotation')
|
785
|
+
self.__rx = v%360.0
|
786
|
+
|
787
|
+
@property
|
788
|
+
def ry(self):
|
789
|
+
return self.__ry
|
790
|
+
|
791
|
+
@ry.setter
|
792
|
+
def ry(self,v):
|
793
|
+
if not isinstance(v,(int,float)):
|
794
|
+
raise ValueError('invalid camera rotation')
|
795
|
+
self.__ry = v%360.0
|
796
|
+
|
797
|
+
@property
|
798
|
+
def objectdict(self):
|
799
|
+
return self.__objectdict
|
800
|
+
|
374
801
|
|
375
802
|
## Overload virtual yapcad.drawable base class dawing methods
|
376
803
|
|
@@ -380,11 +807,26 @@ class pygletDraw(drawable.Drawable):
|
|
380
807
|
super().draw_point(p)
|
381
808
|
self.__arcres=ar
|
382
809
|
|
383
|
-
def draw_line(self,p1,p2):
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
810
|
+
def draw_line(self,p1,p2,entity=None,c1=None,c2=None):
|
811
|
+
|
812
|
+
if not entity:
|
813
|
+
entity=self
|
814
|
+
elist = entity.__lines
|
815
|
+
else:
|
816
|
+
elist = entity.lines
|
817
|
+
color1 = []
|
818
|
+
color2 = []
|
819
|
+
if not c1:
|
820
|
+
color1 = self.thing2color(entity.linecolor,'f')
|
821
|
+
else:
|
822
|
+
color1 = self.thing2color(c1,'f')
|
823
|
+
if not c2:
|
824
|
+
color2 = self.thing2color(entity.linecolor,'f')
|
825
|
+
else:
|
826
|
+
color2 = self.thing2color(c2,'f')
|
827
|
+
elist.append([ ('v3f',(p1[0],p1[1],p1[2],
|
828
|
+
p2[0],p2[1],p2[2])),
|
829
|
+
('c3f',tuple(color1 + color2)) ])
|
388
830
|
|
389
831
|
def draw_arc(self,p,r,start,end):
|
390
832
|
res = self.__arcres
|
@@ -478,9 +920,81 @@ class pygletDraw(drawable.Drawable):
|
|
478
920
|
self.__linestrips.append([ ('v3f', tuple(p2)),\
|
479
921
|
('c3f',tuple(c2)),
|
480
922
|
tuple(i2) ])
|
481
|
-
|
482
923
|
|
483
|
-
def
|
924
|
+
def make_object(self,name,**kwargs):
|
925
|
+
"""
|
926
|
+
Create a new three-dmensional object with specified
|
927
|
+
material properties and 6DOF in world-space that can be
|
928
|
+
animated
|
929
|
+
"""
|
930
|
+
if name in self.__objectdict.keys():
|
931
|
+
raise ValueError('duplicate object key')
|
932
|
+
obj = GeomObject()
|
933
|
+
|
934
|
+
if 'lighting' in kwargs:
|
935
|
+
if kwargs['lighting']:
|
936
|
+
obj.lighting = True
|
937
|
+
else:
|
938
|
+
obj.lighting=False
|
939
|
+
if 'position' in kwargs:
|
940
|
+
x = kwargs['position']
|
941
|
+
if not ispoint(x):
|
942
|
+
raise ValueError('bad position')
|
943
|
+
obj.x = x[0]
|
944
|
+
obj.y = x[1]
|
945
|
+
obj.z = x[2]
|
946
|
+
else:
|
947
|
+
obj.x = 0
|
948
|
+
obj.y = 0
|
949
|
+
obj.z = 0
|
950
|
+
if 'rotation' in kwargs:
|
951
|
+
r = kwargs['rotation']
|
952
|
+
obj.rx = r[0]
|
953
|
+
obj.ry = r[1]
|
954
|
+
obj.rz = r[2]
|
955
|
+
else:
|
956
|
+
obj.rx = 0
|
957
|
+
obj.ry = 0
|
958
|
+
obj.rz = 0
|
959
|
+
if 'material' in kwargs:
|
960
|
+
mat = kwargs['material']
|
961
|
+
if mat in materials:
|
962
|
+
obj.material = materials[mat]
|
963
|
+
m = obj.material.material
|
964
|
+
obj.group = pyglet.model.MaterialGroup(material=m)
|
965
|
+
else:
|
966
|
+
raise ValueError('unknown material')
|
967
|
+
else:
|
968
|
+
obj.material=materials['default']
|
969
|
+
obj.group = self.group
|
970
|
+
|
971
|
+
if 'animate' in kwargs:
|
972
|
+
pyglet.clock.schedule_interval(kwargs['animate'],1/60)
|
973
|
+
|
974
|
+
if 'linecolor' in kwargs:
|
975
|
+
obj.linecolor = kwargs['linecolor']
|
976
|
+
else:
|
977
|
+
obj.linecolor = 'gray'
|
978
|
+
|
979
|
+
obj.batch = graphics.Batch()
|
980
|
+
obj.linebatch = graphics.Batch()
|
981
|
+
obj.surfaces = []
|
982
|
+
obj.lines=[]
|
983
|
+
|
984
|
+
|
985
|
+
self.__objectdict[name] = obj
|
986
|
+
|
987
|
+
def draw_surface(self,points,normals=None,faces=None,name=None):
|
988
|
+
"""
|
989
|
+
render a surface, either as part of default scene geometry
|
990
|
+
(if ``name`` is not specified) or as a part of a named object.
|
991
|
+
"""
|
992
|
+
if not (normals or faces):
|
993
|
+
if not issurface(points):
|
994
|
+
raise ValueError('bad surface passed to draw_surface')
|
995
|
+
normals = points[2]
|
996
|
+
faces = points[3]
|
997
|
+
points = points[1]
|
484
998
|
vrts = []
|
485
999
|
nrms= []
|
486
1000
|
inds = []
|
@@ -490,9 +1004,31 @@ class pygletDraw(drawable.Drawable):
|
|
490
1004
|
nrms+=n[0:3]
|
491
1005
|
for f in faces:
|
492
1006
|
inds+=f[0:3]
|
493
|
-
|
1007
|
+
if not name:
|
1008
|
+
self.__surfaces.append(['surface',vrts,nrms,inds])
|
1009
|
+
else:
|
1010
|
+
obj = self.__objectdict[name]
|
1011
|
+
obj.surfaces.append(['surface',vrts,nrms,inds])
|
1012
|
+
|
1013
|
+
def draw_solid(self,solid,name=None):
|
1014
|
+
"""
|
1015
|
+
Render a solid, either as part of the secene geometry
|
1016
|
+
"""
|
1017
|
+
if not issolid(solid):
|
1018
|
+
raise ValueError('bad solid passed to draw_solid')
|
1019
|
+
for surface in solid[1]:
|
1020
|
+
self.draw_surface(surface,name=name)
|
1021
|
+
|
1022
|
+
## override base-class draw method
|
1023
|
+
def draw(self,x,name=None):
|
1024
|
+
if issolid(x):
|
1025
|
+
self.draw_solid(x,name=name)
|
1026
|
+
elif issurface(x):
|
1027
|
+
self.draw_surface(x,name=name)
|
1028
|
+
else:
|
1029
|
+
super().draw(x)
|
494
1030
|
|
495
|
-
##
|
1031
|
+
## override base-class virtual display method
|
496
1032
|
def display(self):
|
497
1033
|
self.makeBatches()
|
498
1034
|
pyglet.app.run()
|