Source code for scfile.formats.obj.encoder
import numpy as np
from scfile.core import FileEncoder, ModelContent
from scfile.enums import ByteOrder, FileFormat
from scfile.structures import models as S
from scfile.structures.models import Flag
from scfile.structures.models import transforms as T
from . import faces
[docs]
class ObjEncoder(FileEncoder[ModelContent]):
format = FileFormat.OBJ
order = ByteOrder.LITTLE
transforms = [T.unique_names, T.flip_uv]
[docs]
def serialize(self):
self._add_meshes()
def _add_meshes(self):
offset = 1
for mesh in self.data.scene.meshes:
self._writeutf8(f"o {mesh.name}\n")
self._writeutf8(f"usemtl {mesh.material}\n")
self._add_geometric_vertices(mesh)
if self.data.flags[Flag.UV]:
self._add_texture_coordinates(mesh)
if self.data.flags[Flag.NORMALS] or self.data.flags[Flag.TANGENTS]:
self._add_vertex_normals(mesh)
self._writeutf8(f"g {mesh.name}\n")
self._add_polygonal_faces(mesh, offset)
offset += len(mesh.vertices)
def _vectorize(self, template: bytes, data: np.ndarray, count: int):
return (template * count) % tuple(data.flatten().tolist())
def _add_geometric_vertices(self, mesh: S.ModelMesh):
template = b"v %.6f %.6f %.6f\n"
self.write(self._vectorize(template, mesh.vertices, len(mesh.vertices)))
self.write(b"\n")
def _add_texture_coordinates(self, mesh: S.ModelMesh):
template = b"vt %.6f %.6f\n"
self.write(self._vectorize(template, mesh.uv1, len(mesh.vertices)))
self.write(b"\n")
def _add_vertex_normals(self, mesh: S.ModelMesh):
template = b"vn %.6f %.6f %.6f\n"
self.write(self._vectorize(template, mesh.normals, len(mesh.vertices)))
self.write(b"\n")
def _add_polygonal_faces(self, mesh: S.ModelMesh, offset: int):
flags = faces.Flags(uv=self.data.flags[Flag.UV], normals=self.data.flags[Flag.NORMALS])
template = faces.TEMPLATE[flags]
polygons = mesh.polygons + offset
self._writeutf8("\n".join([template.format(a=a, b=b, c=c) for a, b, c in polygons.tolist()]))
self.write(b"\n\n")