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")