Source code for scfile.formats.obj.encoder
import numpy as np
from scfile.core import FileEncoder, ModelContent
from scfile.enums import FileFormat
from scfile.structures.flags import Flag
from scfile.structures.mesh import ModelMesh
from . import faces
[docs]
class ObjEncoder(FileEncoder[ModelContent]):
format = FileFormat.OBJ
[docs]
def prepare(self):
self.data.scene.ensure_unique_names()
if self.data.flags[Flag.UV]:
self.data.scene.flip_v_textures()
[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]:
self._add_vertex_normals(mesh)
self._writeutf8(f"g {mesh.name}\n")
self._add_polygonal_faces(mesh, offset)
offset += mesh.count.vertices
def _vectorize(self, template: bytes, data: np.ndarray, count: int):
return (template * count) % tuple(data.flatten().tolist())
def _add_geometric_vertices(self, mesh: ModelMesh):
template = b"v %.6f %.6f %.6f\n"
self.write(self._vectorize(template, mesh.positions, mesh.count.vertices))
self.write(b"\n")
def _add_texture_coordinates(self, mesh: ModelMesh):
template = b"vt %.6f %.6f\n"
self.write(self._vectorize(template, mesh.textures, mesh.count.vertices))
self.write(b"\n")
def _add_vertex_normals(self, mesh: ModelMesh):
template = b"vn %.6f %.6f %.6f\n"
self.write(self._vectorize(template, mesh.normals, mesh.count.vertices))
self.write(b"\n")
def _add_polygonal_faces(self, mesh: 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")