pyffi.formats.tri
— TRI (.tri)¶
A .tri file contains facial expression data, that is, morphs for dynamic expressions such as smile, frown, and so on.
Implementation¶
-
class
pyffi.formats.tri.
TriFormat
[source]¶ Bases:
pyffi.object_models.xml.FileFormat
This class implements the TRI format.
-
class
FileSignature
(**kwargs)[source]¶ Bases:
pyffi.object_models.xml.basic.BasicBase
Basic type which implements the header of a TRI file.
-
get_hash
(data=None)[source]¶ Return a hash value for this value.
- Returns
An immutable object that can be used as a hash.
-
get_size
(data=None)[source]¶ Return number of bytes the header string occupies in a file.
- Returns
Number of bytes.
-
-
class
FileVersion
(template=None, argument=None, parent=None)[source]¶ Bases:
pyffi.object_models.xml.basic.BasicBase
-
class
Header
(template=None, argument=None, parent=None)[source]¶ Bases:
pyffi.formats.tri._Header
,pyffi.object_models.Data
A class to contain the actual tri data.
-
get_global_child_nodes
(edge_filter=(True, True))[source]¶ Generator which yields all children of this item in the global view, of given edge type (default is edges of type 0).
Override this method.
- Returns
Generator for global node children.
-
inspect
(stream)[source]¶ Quickly checks if stream contains TRI data, and reads everything up to the arrays.
- Parameters
stream (file) – The stream to inspect.
-
-
class
ModifierRecord
(template=None, argument=None, parent=None)¶ Bases:
pyffi.object_models.xml.struct_.StructBase
A modifier replaces the vertices from the base model (Header.vertices) with those in Header.modifier_vertices. Note that Header.modifier_vertices counts up from the first modifier onwards. For example, if you were to take the 4th vertex to be modified in the 2nd modifier and the size of the 1st modifier was 10 vertices, then you would need Header.modifier_vertices[14]. Therefore, Header.num_modifier_vertices = sum(modifier.num_vertices_to_modify for modifier in Header.modifiers).
-
class
MorphRecord
(template=None, argument=None, parent=None)[source]¶ Bases:
pyffi.formats.tri._MorphRecord
,object
>>> # create morph with 3 vertices. >>> morph = TriFormat.MorphRecord(argument=3) >>> morph.set_relative_vertices( ... [(3, 5, 2), (1, 3, 2), (-9, 3, -1)]) >>> # scale should be 9/32768.0 = 0.0002746... >>> morph.scale 0.0002746... >>> for vert in morph.get_relative_vertices(): ... print([int(1000 * x + 0.5) for x in vert]) [3000, 5000, 2000] [1000, 3000, 2000] [-8999, 3000, -999]
-
apply_scale
(scale)[source]¶ Apply scale factor to data.
>>> # create morph with 3 vertices. >>> morph = TriFormat.MorphRecord(argument=3) >>> morph.set_relative_vertices( ... [(3, 5, 2), (1, 3, 2), (-9, 3, -1)]) >>> morph.apply_scale(2) >>> for vert in morph.get_relative_vertices(): ... print([int(1000 * x + 0.5) for x in vert]) [6000, 10000, 4000] [2000, 6000, 4000] [-17999, 6000, -1999]
-
-
class
QuadFace
(template=None, argument=None, parent=None)¶ Bases:
pyffi.object_models.xml.struct_.StructBase
Not used by the Oblivion engine as it’s tri based.
-
class
SizedStringZ
(**kwargs)[source]¶ Bases:
pyffi.object_models.common.SizedString
-
get_size
(data=None)[source]¶ Return number of bytes this type occupies in a file.
- Returns
Number of bytes.
-
-
byte
¶ alias of
pyffi.object_models.common.Byte
-
char
¶ alias of
pyffi.object_models.common.Char
-
float
¶ alias of
pyffi.object_models.common.Float
-
int
¶ alias of
pyffi.object_models.common.Int
-
short
¶ alias of
pyffi.object_models.common.Short
-
ubyte
¶ alias of
pyffi.object_models.common.UByte
-
uint
¶ alias of
pyffi.object_models.common.UInt
-
ushort
¶ alias of
pyffi.object_models.common.UShort
-
class
Regression tests¶
Read a TRI file¶
>>> # check and read tri file
>>> from os.path import dirname
>>> dirpath = __file__
>>> for i in range(4): #recurse up to root repo dir
... dirpath = dirname(dirpath)
>>> repo_root = dirpath
>>> format_root = os.path.join(repo_root, 'tests', 'formats', 'tri')
>>> file = os.path.join(format_root, 'mmouthxivilai.tri')
>>> stream = open(file, 'rb')
>>> data = TriFormat.Data()
>>> data.inspect(stream)
>>> # do some stuff with header?
>>> data.num_vertices
89
>>> data.num_tri_faces
215
>>> data.num_quad_faces
0
>>> data.num_uvs
89
>>> data.num_morphs
18
>>> data.read(stream)
>>> print([str(morph.name.decode("ascii")) for morph in data.morphs])
['Fear', 'Surprise', 'Aah', 'BigAah', 'BMP', 'ChJSh', 'DST', 'Eee', 'Eh', 'FV', 'I', 'K', 'N', 'Oh', 'OohQ', 'R', 'Th', 'W']
Parse all TRI files in a directory tree¶
>>> for stream, data in TriFormat.walkData(format_root):
... try:
... # the replace call makes the doctest also pass on windows
... os_path = stream.name
... split = (os_path.split(os.sep))[-4:]
... rejoin = os.path.join(*split).replace(os.sep, "/")
... print("reading %s" % rejoin)
... except Exception:
... print(
... "Warning: read failed due corrupt file,"
... " corrupt format description, or bug.")
reading tests/formats/tri/mmouthxivilai.tri
Create an TRI file from scratch and write to file¶
>>> data = TriFormat.Data()
>>> from tempfile import TemporaryFile
>>> stream = TemporaryFile()
>>> data.write(stream)