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/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 Material and Group for the Model
88
- diffuse = [0.5, 0.5, 0.3, 1.0]
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
- diffuse = [0.02, 0.02, 0.023, 1.0]
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
- epsP = point(epsilon,epsilon,epsilon)
113
- epsM = point(-epsilon,-epsilon,-epsilon)
114
-
115
- ## utility funtion to update bounding box based on a list of points
116
- def upbb(pp,box):
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
- vert = s[0]
161
- norm = s[1]
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 = False
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
- color = self.thing2color(self.linecolor,'f')
385
- self.__lines.append([ ('v3f',(p1[0],p1[1],p1[2],
386
- p2[0],p2[1],p2[2])),
387
- ('c3f',tuple(color + color)) ])
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 draw_surface(self,points,normals,faces):
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
- self.__surfaces.append([vrts,nrms,inds])
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
- ## overload base-class virtual display method
1031
+ ## override base-class virtual display method
496
1032
  def display(self):
497
1033
  self.makeBatches()
498
1034
  pyglet.app.run()