pyrender-maintained 1.0.0__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.
- pyrender/__init__.py +24 -0
- pyrender/camera.py +435 -0
- pyrender/constants.py +149 -0
- pyrender/font.py +272 -0
- pyrender/light.py +382 -0
- pyrender/material.py +705 -0
- pyrender/mesh.py +328 -0
- pyrender/node.py +263 -0
- pyrender/offscreen.py +160 -0
- pyrender/platforms/__init__.py +6 -0
- pyrender/platforms/base.py +73 -0
- pyrender/platforms/egl.py +219 -0
- pyrender/platforms/osmesa.py +59 -0
- pyrender/platforms/pyglet_platform.py +90 -0
- pyrender/primitive.py +489 -0
- pyrender/renderer.py +1328 -0
- pyrender/sampler.py +102 -0
- pyrender/scene.py +585 -0
- pyrender/shader_program.py +283 -0
- pyrender/texture.py +259 -0
- pyrender/trackball.py +216 -0
- pyrender/utils.py +115 -0
- pyrender/version.py +1 -0
- pyrender/viewer.py +1157 -0
- pyrender_maintained-1.0.0.dist-info/METADATA +55 -0
- pyrender_maintained-1.0.0.dist-info/RECORD +29 -0
- pyrender_maintained-1.0.0.dist-info/WHEEL +5 -0
- pyrender_maintained-1.0.0.dist-info/licenses/LICENSE +21 -0
- pyrender_maintained-1.0.0.dist-info/top_level.txt +1 -0
pyrender/primitive.py
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
"""Primitives, conforming to the glTF 2.0 standards as specified in
|
|
2
|
+
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-primitive
|
|
3
|
+
|
|
4
|
+
Author: Matthew Matl
|
|
5
|
+
"""
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from OpenGL.GL import *
|
|
9
|
+
|
|
10
|
+
from .material import Material, MetallicRoughnessMaterial
|
|
11
|
+
from .constants import FLOAT_SZ, UINT_SZ, BufFlags, GLTF
|
|
12
|
+
from .utils import format_color_array
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Primitive(object):
|
|
16
|
+
"""A primitive object which can be rendered.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
positions : (n, 3) float
|
|
21
|
+
XYZ vertex positions.
|
|
22
|
+
normals : (n, 3) float
|
|
23
|
+
Normalized XYZ vertex normals.
|
|
24
|
+
tangents : (n, 4) float
|
|
25
|
+
XYZW vertex tangents where the w component is a sign value
|
|
26
|
+
(either +1 or -1) indicating the handedness of the tangent basis.
|
|
27
|
+
texcoord_0 : (n, 2) float
|
|
28
|
+
The first set of UV texture coordinates.
|
|
29
|
+
texcoord_1 : (n, 2) float
|
|
30
|
+
The second set of UV texture coordinates.
|
|
31
|
+
color_0 : (n, 4) float
|
|
32
|
+
RGBA vertex colors.
|
|
33
|
+
joints_0 : (n, 4) float
|
|
34
|
+
Joint information.
|
|
35
|
+
weights_0 : (n, 4) float
|
|
36
|
+
Weight information for morphing.
|
|
37
|
+
indices : (m, 3) int
|
|
38
|
+
Face indices for triangle meshes or fans.
|
|
39
|
+
material : :class:`Material`
|
|
40
|
+
The material to apply to this primitive when rendering.
|
|
41
|
+
mode : int
|
|
42
|
+
The type of primitives to render, one of the following:
|
|
43
|
+
|
|
44
|
+
- ``0``: POINTS
|
|
45
|
+
- ``1``: LINES
|
|
46
|
+
- ``2``: LINE_LOOP
|
|
47
|
+
- ``3``: LINE_STRIP
|
|
48
|
+
- ``4``: TRIANGLES
|
|
49
|
+
- ``5``: TRIANGLES_STRIP
|
|
50
|
+
- ``6``: TRIANGLES_FAN
|
|
51
|
+
targets : (k,) int
|
|
52
|
+
Morph target indices.
|
|
53
|
+
poses : (x,4,4), float
|
|
54
|
+
Array of 4x4 transformation matrices for instancing this object.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(self,
|
|
58
|
+
positions,
|
|
59
|
+
normals=None,
|
|
60
|
+
tangents=None,
|
|
61
|
+
texcoord_0=None,
|
|
62
|
+
texcoord_1=None,
|
|
63
|
+
color_0=None,
|
|
64
|
+
joints_0=None,
|
|
65
|
+
weights_0=None,
|
|
66
|
+
indices=None,
|
|
67
|
+
material=None,
|
|
68
|
+
mode=None,
|
|
69
|
+
targets=None,
|
|
70
|
+
poses=None):
|
|
71
|
+
|
|
72
|
+
if mode is None:
|
|
73
|
+
mode = GLTF.TRIANGLES
|
|
74
|
+
|
|
75
|
+
self.positions = positions
|
|
76
|
+
self.normals = normals
|
|
77
|
+
self.tangents = tangents
|
|
78
|
+
self.texcoord_0 = texcoord_0
|
|
79
|
+
self.texcoord_1 = texcoord_1
|
|
80
|
+
self.color_0 = color_0
|
|
81
|
+
self.joints_0 = joints_0
|
|
82
|
+
self.weights_0 = weights_0
|
|
83
|
+
self.indices = indices
|
|
84
|
+
self.material = material
|
|
85
|
+
self.mode = mode
|
|
86
|
+
self.targets = targets
|
|
87
|
+
self.poses = poses
|
|
88
|
+
|
|
89
|
+
self._bounds = None
|
|
90
|
+
self._vaid = None
|
|
91
|
+
self._buffers = []
|
|
92
|
+
self._is_transparent = None
|
|
93
|
+
self._buf_flags = None
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def positions(self):
|
|
97
|
+
"""(n,3) float : XYZ vertex positions.
|
|
98
|
+
"""
|
|
99
|
+
return self._positions
|
|
100
|
+
|
|
101
|
+
@positions.setter
|
|
102
|
+
def positions(self, value):
|
|
103
|
+
value = np.asanyarray(value, dtype=np.float32)
|
|
104
|
+
self._positions = np.ascontiguousarray(value)
|
|
105
|
+
self._bounds = None
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def normals(self):
|
|
109
|
+
"""(n,3) float : Normalized XYZ vertex normals.
|
|
110
|
+
"""
|
|
111
|
+
return self._normals
|
|
112
|
+
|
|
113
|
+
@normals.setter
|
|
114
|
+
def normals(self, value):
|
|
115
|
+
if value is not None:
|
|
116
|
+
value = np.asanyarray(value, dtype=np.float32)
|
|
117
|
+
value = np.ascontiguousarray(value)
|
|
118
|
+
if value.shape != self.positions.shape:
|
|
119
|
+
raise ValueError('Incorrect normals shape')
|
|
120
|
+
self._normals = value
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def tangents(self):
|
|
124
|
+
"""(n,4) float : XYZW vertex tangents.
|
|
125
|
+
"""
|
|
126
|
+
return self._tangents
|
|
127
|
+
|
|
128
|
+
@tangents.setter
|
|
129
|
+
def tangents(self, value):
|
|
130
|
+
if value is not None:
|
|
131
|
+
value = np.asanyarray(value, dtype=np.float32)
|
|
132
|
+
value = np.ascontiguousarray(value)
|
|
133
|
+
if value.shape != (self.positions.shape[0], 4):
|
|
134
|
+
raise ValueError('Incorrect tangent shape')
|
|
135
|
+
self._tangents = value
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def texcoord_0(self):
|
|
139
|
+
"""(n,2) float : The first set of UV texture coordinates.
|
|
140
|
+
"""
|
|
141
|
+
return self._texcoord_0
|
|
142
|
+
|
|
143
|
+
@texcoord_0.setter
|
|
144
|
+
def texcoord_0(self, value):
|
|
145
|
+
if value is not None:
|
|
146
|
+
value = np.asanyarray(value, dtype=np.float32)
|
|
147
|
+
value = np.ascontiguousarray(value)
|
|
148
|
+
if (value.ndim != 2 or value.shape[0] != self.positions.shape[0] or
|
|
149
|
+
value.shape[1] < 2):
|
|
150
|
+
raise ValueError('Incorrect texture coordinate shape')
|
|
151
|
+
if value.shape[1] > 2:
|
|
152
|
+
value = value[:,:2]
|
|
153
|
+
self._texcoord_0 = value
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def texcoord_1(self):
|
|
157
|
+
"""(n,2) float : The second set of UV texture coordinates.
|
|
158
|
+
"""
|
|
159
|
+
return self._texcoord_1
|
|
160
|
+
|
|
161
|
+
@texcoord_1.setter
|
|
162
|
+
def texcoord_1(self, value):
|
|
163
|
+
if value is not None:
|
|
164
|
+
value = np.asanyarray(value, dtype=np.float32)
|
|
165
|
+
value = np.ascontiguousarray(value)
|
|
166
|
+
if (value.ndim != 2 or value.shape[0] != self.positions.shape[0] or
|
|
167
|
+
value.shape[1] != 2):
|
|
168
|
+
raise ValueError('Incorrect texture coordinate shape')
|
|
169
|
+
self._texcoord_1 = value
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def color_0(self):
|
|
173
|
+
"""(n,4) float : RGBA vertex colors.
|
|
174
|
+
"""
|
|
175
|
+
return self._color_0
|
|
176
|
+
|
|
177
|
+
@color_0.setter
|
|
178
|
+
def color_0(self, value):
|
|
179
|
+
if value is not None:
|
|
180
|
+
value = np.ascontiguousarray(
|
|
181
|
+
format_color_array(value, shape=(len(self.positions), 4))
|
|
182
|
+
)
|
|
183
|
+
self._is_transparent = None
|
|
184
|
+
self._color_0 = value
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def joints_0(self):
|
|
188
|
+
"""(n,4) float : Joint information.
|
|
189
|
+
"""
|
|
190
|
+
return self._joints_0
|
|
191
|
+
|
|
192
|
+
@joints_0.setter
|
|
193
|
+
def joints_0(self, value):
|
|
194
|
+
self._joints_0 = value
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def weights_0(self):
|
|
198
|
+
"""(n,4) float : Weight information for morphing.
|
|
199
|
+
"""
|
|
200
|
+
return self._weights_0
|
|
201
|
+
|
|
202
|
+
@weights_0.setter
|
|
203
|
+
def weights_0(self, value):
|
|
204
|
+
self._weights_0 = value
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def indices(self):
|
|
208
|
+
"""(m,3) int : Face indices for triangle meshes or fans.
|
|
209
|
+
"""
|
|
210
|
+
return self._indices
|
|
211
|
+
|
|
212
|
+
@indices.setter
|
|
213
|
+
def indices(self, value):
|
|
214
|
+
if value is not None:
|
|
215
|
+
value = np.asanyarray(value, dtype=np.float32)
|
|
216
|
+
value = np.ascontiguousarray(value)
|
|
217
|
+
self._indices = value
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def material(self):
|
|
221
|
+
""":class:`Material` : The material for this primitive.
|
|
222
|
+
"""
|
|
223
|
+
return self._material
|
|
224
|
+
|
|
225
|
+
@material.setter
|
|
226
|
+
def material(self, value):
|
|
227
|
+
# Create default material
|
|
228
|
+
if value is None:
|
|
229
|
+
value = MetallicRoughnessMaterial()
|
|
230
|
+
else:
|
|
231
|
+
if not isinstance(value, Material):
|
|
232
|
+
raise TypeError('Object material must be of type Material')
|
|
233
|
+
self._material = value
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def mode(self):
|
|
237
|
+
"""int : The type of primitive to render.
|
|
238
|
+
"""
|
|
239
|
+
return self._mode
|
|
240
|
+
|
|
241
|
+
@mode.setter
|
|
242
|
+
def mode(self, value):
|
|
243
|
+
value = int(value)
|
|
244
|
+
if value < GLTF.POINTS or value > GLTF.TRIANGLE_FAN:
|
|
245
|
+
raise ValueError('Invalid mode')
|
|
246
|
+
self._mode = value
|
|
247
|
+
|
|
248
|
+
@property
|
|
249
|
+
def targets(self):
|
|
250
|
+
"""(k,) int : Morph target indices.
|
|
251
|
+
"""
|
|
252
|
+
return self._targets
|
|
253
|
+
|
|
254
|
+
@targets.setter
|
|
255
|
+
def targets(self, value):
|
|
256
|
+
self._targets = value
|
|
257
|
+
|
|
258
|
+
@property
|
|
259
|
+
def poses(self):
|
|
260
|
+
"""(x,4,4) float : Homogenous transforms for instancing this primitive.
|
|
261
|
+
"""
|
|
262
|
+
return self._poses
|
|
263
|
+
|
|
264
|
+
@poses.setter
|
|
265
|
+
def poses(self, value):
|
|
266
|
+
if value is not None:
|
|
267
|
+
value = np.asanyarray(value, dtype=np.float32)
|
|
268
|
+
value = np.ascontiguousarray(value)
|
|
269
|
+
if value.ndim == 2:
|
|
270
|
+
value = value[np.newaxis,:,:]
|
|
271
|
+
if value.shape[1] != 4 or value.shape[2] != 4:
|
|
272
|
+
raise ValueError('Pose matrices must be of shape (n,4,4), '
|
|
273
|
+
'got {}'.format(value.shape))
|
|
274
|
+
self._poses = value
|
|
275
|
+
self._bounds = None
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def bounds(self):
|
|
279
|
+
if self._bounds is None:
|
|
280
|
+
self._bounds = self._compute_bounds()
|
|
281
|
+
return self._bounds
|
|
282
|
+
|
|
283
|
+
@property
|
|
284
|
+
def centroid(self):
|
|
285
|
+
"""(3,) float : The centroid of the primitive's AABB.
|
|
286
|
+
"""
|
|
287
|
+
return np.mean(self.bounds, axis=0)
|
|
288
|
+
|
|
289
|
+
@property
|
|
290
|
+
def extents(self):
|
|
291
|
+
"""(3,) float : The lengths of the axes of the primitive's AABB.
|
|
292
|
+
"""
|
|
293
|
+
return np.diff(self.bounds, axis=0).reshape(-1)
|
|
294
|
+
|
|
295
|
+
@property
|
|
296
|
+
def scale(self):
|
|
297
|
+
"""(3,) float : The length of the diagonal of the primitive's AABB.
|
|
298
|
+
"""
|
|
299
|
+
return np.linalg.norm(self.extents)
|
|
300
|
+
|
|
301
|
+
@property
|
|
302
|
+
def buf_flags(self):
|
|
303
|
+
"""int : The flags for the render buffer.
|
|
304
|
+
"""
|
|
305
|
+
if self._buf_flags is None:
|
|
306
|
+
self._buf_flags = self._compute_buf_flags()
|
|
307
|
+
return self._buf_flags
|
|
308
|
+
|
|
309
|
+
def delete(self):
|
|
310
|
+
self._unbind()
|
|
311
|
+
self._remove_from_context()
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def is_transparent(self):
|
|
315
|
+
"""bool : If True, the mesh is partially-transparent.
|
|
316
|
+
"""
|
|
317
|
+
return self._compute_transparency()
|
|
318
|
+
|
|
319
|
+
def _add_to_context(self):
|
|
320
|
+
if self._vaid is not None:
|
|
321
|
+
raise ValueError('Mesh is already bound to a context')
|
|
322
|
+
|
|
323
|
+
# Generate and bind VAO
|
|
324
|
+
self._vaid = glGenVertexArrays(1)
|
|
325
|
+
glBindVertexArray(self._vaid)
|
|
326
|
+
|
|
327
|
+
#######################################################################
|
|
328
|
+
# Fill vertex buffer
|
|
329
|
+
#######################################################################
|
|
330
|
+
|
|
331
|
+
# Generate and bind vertex buffer
|
|
332
|
+
vertexbuffer = glGenBuffers(1)
|
|
333
|
+
self._buffers.append(vertexbuffer)
|
|
334
|
+
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer)
|
|
335
|
+
|
|
336
|
+
# positions
|
|
337
|
+
vertex_data = self.positions
|
|
338
|
+
attr_sizes = [3]
|
|
339
|
+
|
|
340
|
+
# Normals
|
|
341
|
+
if self.normals is not None:
|
|
342
|
+
vertex_data = np.hstack((vertex_data, self.normals))
|
|
343
|
+
attr_sizes.append(3)
|
|
344
|
+
|
|
345
|
+
# Tangents
|
|
346
|
+
if self.tangents is not None:
|
|
347
|
+
vertex_data = np.hstack((vertex_data, self.tangents))
|
|
348
|
+
attr_sizes.append(4)
|
|
349
|
+
|
|
350
|
+
# Texture Coordinates
|
|
351
|
+
if self.texcoord_0 is not None:
|
|
352
|
+
vertex_data = np.hstack((vertex_data, self.texcoord_0))
|
|
353
|
+
attr_sizes.append(2)
|
|
354
|
+
if self.texcoord_1 is not None:
|
|
355
|
+
vertex_data = np.hstack((vertex_data, self.texcoord_1))
|
|
356
|
+
attr_sizes.append(2)
|
|
357
|
+
|
|
358
|
+
# Color
|
|
359
|
+
if self.color_0 is not None:
|
|
360
|
+
vertex_data = np.hstack((vertex_data, self.color_0))
|
|
361
|
+
attr_sizes.append(4)
|
|
362
|
+
|
|
363
|
+
# TODO JOINTS AND WEIGHTS
|
|
364
|
+
# PASS
|
|
365
|
+
|
|
366
|
+
# Copy data to buffer
|
|
367
|
+
vertex_data = np.ascontiguousarray(
|
|
368
|
+
vertex_data.flatten().astype(np.float32)
|
|
369
|
+
)
|
|
370
|
+
glBufferData(
|
|
371
|
+
GL_ARRAY_BUFFER, FLOAT_SZ * len(vertex_data),
|
|
372
|
+
vertex_data, GL_STATIC_DRAW
|
|
373
|
+
)
|
|
374
|
+
total_sz = sum(attr_sizes)
|
|
375
|
+
offset = 0
|
|
376
|
+
for i, sz in enumerate(attr_sizes):
|
|
377
|
+
glVertexAttribPointer(
|
|
378
|
+
i, sz, GL_FLOAT, GL_FALSE, FLOAT_SZ * total_sz,
|
|
379
|
+
ctypes.c_void_p(FLOAT_SZ * offset)
|
|
380
|
+
)
|
|
381
|
+
glEnableVertexAttribArray(i)
|
|
382
|
+
offset += sz
|
|
383
|
+
|
|
384
|
+
#######################################################################
|
|
385
|
+
# Fill model matrix buffer
|
|
386
|
+
#######################################################################
|
|
387
|
+
|
|
388
|
+
if self.poses is not None:
|
|
389
|
+
pose_data = np.ascontiguousarray(
|
|
390
|
+
np.transpose(self.poses, [0,2,1]).flatten().astype(np.float32)
|
|
391
|
+
)
|
|
392
|
+
else:
|
|
393
|
+
pose_data = np.ascontiguousarray(
|
|
394
|
+
np.eye(4).flatten().astype(np.float32)
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
modelbuffer = glGenBuffers(1)
|
|
398
|
+
self._buffers.append(modelbuffer)
|
|
399
|
+
glBindBuffer(GL_ARRAY_BUFFER, modelbuffer)
|
|
400
|
+
glBufferData(
|
|
401
|
+
GL_ARRAY_BUFFER, FLOAT_SZ * len(pose_data),
|
|
402
|
+
pose_data, GL_STATIC_DRAW
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
for i in range(0, 4):
|
|
406
|
+
idx = i + len(attr_sizes)
|
|
407
|
+
glEnableVertexAttribArray(idx)
|
|
408
|
+
glVertexAttribPointer(
|
|
409
|
+
idx, 4, GL_FLOAT, GL_FALSE, FLOAT_SZ * 4 * 4,
|
|
410
|
+
ctypes.c_void_p(4 * FLOAT_SZ * i)
|
|
411
|
+
)
|
|
412
|
+
glVertexAttribDivisor(idx, 1)
|
|
413
|
+
|
|
414
|
+
#######################################################################
|
|
415
|
+
# Fill element buffer
|
|
416
|
+
#######################################################################
|
|
417
|
+
if self.indices is not None:
|
|
418
|
+
elementbuffer = glGenBuffers(1)
|
|
419
|
+
self._buffers.append(elementbuffer)
|
|
420
|
+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer)
|
|
421
|
+
glBufferData(GL_ELEMENT_ARRAY_BUFFER, UINT_SZ * self.indices.size,
|
|
422
|
+
self.indices.flatten().astype(np.uint32),
|
|
423
|
+
GL_STATIC_DRAW)
|
|
424
|
+
|
|
425
|
+
glBindVertexArray(0)
|
|
426
|
+
|
|
427
|
+
def _remove_from_context(self):
|
|
428
|
+
if self._vaid is not None:
|
|
429
|
+
glDeleteVertexArrays(1, [self._vaid])
|
|
430
|
+
glDeleteBuffers(len(self._buffers), self._buffers)
|
|
431
|
+
self._vaid = None
|
|
432
|
+
self._buffers = []
|
|
433
|
+
|
|
434
|
+
def _in_context(self):
|
|
435
|
+
return self._vaid is not None
|
|
436
|
+
|
|
437
|
+
def _bind(self):
|
|
438
|
+
if self._vaid is None:
|
|
439
|
+
raise ValueError('Cannot bind a Mesh that has not been added '
|
|
440
|
+
'to a context')
|
|
441
|
+
glBindVertexArray(self._vaid)
|
|
442
|
+
|
|
443
|
+
def _unbind(self):
|
|
444
|
+
glBindVertexArray(0)
|
|
445
|
+
|
|
446
|
+
def _compute_bounds(self):
|
|
447
|
+
"""Compute the bounds of this object.
|
|
448
|
+
"""
|
|
449
|
+
# Compute bounds of this object
|
|
450
|
+
bounds = np.array([np.min(self.positions, axis=0),
|
|
451
|
+
np.max(self.positions, axis=0)])
|
|
452
|
+
|
|
453
|
+
# If instanced, compute translations for approximate bounds
|
|
454
|
+
if self.poses is not None:
|
|
455
|
+
bounds += np.array([np.min(self.poses[:,:3,3], axis=0),
|
|
456
|
+
np.max(self.poses[:,:3,3], axis=0)])
|
|
457
|
+
return bounds
|
|
458
|
+
|
|
459
|
+
def _compute_transparency(self):
|
|
460
|
+
"""Compute whether or not this object is transparent.
|
|
461
|
+
"""
|
|
462
|
+
if self.material.is_transparent:
|
|
463
|
+
return True
|
|
464
|
+
if self._is_transparent is None:
|
|
465
|
+
self._is_transparent = False
|
|
466
|
+
if self.color_0 is not None:
|
|
467
|
+
if np.any(self._color_0[:,3] != 1.0):
|
|
468
|
+
self._is_transparent = True
|
|
469
|
+
return self._is_transparent
|
|
470
|
+
|
|
471
|
+
def _compute_buf_flags(self):
|
|
472
|
+
buf_flags = BufFlags.POSITION
|
|
473
|
+
|
|
474
|
+
if self.normals is not None:
|
|
475
|
+
buf_flags |= BufFlags.NORMAL
|
|
476
|
+
if self.tangents is not None:
|
|
477
|
+
buf_flags |= BufFlags.TANGENT
|
|
478
|
+
if self.texcoord_0 is not None:
|
|
479
|
+
buf_flags |= BufFlags.TEXCOORD_0
|
|
480
|
+
if self.texcoord_1 is not None:
|
|
481
|
+
buf_flags |= BufFlags.TEXCOORD_1
|
|
482
|
+
if self.color_0 is not None:
|
|
483
|
+
buf_flags |= BufFlags.COLOR_0
|
|
484
|
+
if self.joints_0 is not None:
|
|
485
|
+
buf_flags |= BufFlags.JOINTS_0
|
|
486
|
+
if self.weights_0 is not None:
|
|
487
|
+
buf_flags |= BufFlags.WEIGHTS_0
|
|
488
|
+
|
|
489
|
+
return buf_flags
|