94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
'''
|
|
ModernGL extension for storing mesh data
|
|
[andreika]: Modified to support vertex colors instead of texture coords
|
|
'''
|
|
|
|
import logging
|
|
import re
|
|
import struct
|
|
|
|
from pyrr import aabb
|
|
|
|
|
|
log = logging.getLogger('ModernGL.ext.obj')
|
|
|
|
RE_COMMENT = re.compile(r'#[^\n]*\n', flags=re.M)
|
|
RE_VERT = re.compile(r'^v\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)$')
|
|
RE_COLOR = re.compile(r'^vc\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)(?:\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?))?$')
|
|
RE_NORM = re.compile(r'^vn\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)\s+(-?\d+(?:\.\d+)?(?:[Ee]-?\d+)?)$')
|
|
RE_FACE = re.compile(r'^f\s+(\d+)(/(\d+)?(/(\d+))?)?\s+(\d+)(/(\d+)?(/(\d+))?)?\s+(\d+)(/(\d+)?(/(\d+))?)?$')
|
|
|
|
PACKER = 'lambda vx, vy, vz, cx, cy, cz, nx, ny, nz: struct.pack("%df", %s)'
|
|
|
|
|
|
def default_packer(vx, vy, vz, cx, cy, cz, nx, ny, nz):
|
|
return struct.pack('9f', vx, vy, vz, cx, cy, cz, nx, ny, nz)
|
|
|
|
|
|
def int_or_none(x):
|
|
return None if x is None else int(x)
|
|
|
|
|
|
def safe_float(x):
|
|
return 0.0 if x is None else float(x)
|
|
|
|
|
|
class Mesh:
|
|
def __init__(self, vert, color, norm, face):
|
|
self.vert = vert
|
|
self.color = color
|
|
self.norm = norm
|
|
self.face = face
|
|
# we need AABB to zoom in the model
|
|
self.aabb = aabb.create_zeros()
|
|
|
|
def pack(self, packer=default_packer) -> bytes:
|
|
'''
|
|
Args:
|
|
packer (str or lambda): The vertex attributes to pack.
|
|
|
|
Returns:
|
|
bytes: The packed vertex data.
|
|
|
|
Examples:
|
|
|
|
.. code-block:: python
|
|
|
|
import ModernGL
|
|
from ModernGL.ext import obj
|
|
|
|
model = obj.Obj.open('box.obj')
|
|
|
|
# default packer
|
|
data = model.pack()
|
|
|
|
# same as the default packer
|
|
data = model.pack('vx vy vz tx ty tz nx ny nz')
|
|
|
|
# pack vertices
|
|
data = model.pack('vx vy vz')
|
|
|
|
# pack vertices and texture coordinates (xy)
|
|
data = model.pack('vx vy vz tx ty')
|
|
|
|
# pack vertices and normals
|
|
data = model.pack('vx vy vz nx ny nz')
|
|
|
|
# pack vertices with padding
|
|
data = model.pack('vx vy vz 0.0')
|
|
'''
|
|
|
|
if isinstance(packer, str):
|
|
nodes = packer.split()
|
|
packer = eval(PACKER % (len(nodes), ', '.join(nodes)))
|
|
|
|
result = bytearray()
|
|
|
|
for v, t, n in self.face:
|
|
vx, vy, vz = self.vert[v - 1]
|
|
cx, cy, cz = self.color[t - 1] if t is not None else (0.0, 0.0, 0.0)
|
|
nx, ny, nz = self.norm[n - 1] if n is not None else (0.0, 0.0, 0.0)
|
|
result += packer(vx, vy, vz, cx, cy, cz, nx, ny, nz)
|
|
|
|
return bytes(result)
|