Ready for serialization mesh data structure
目次
Introduction
Blender has a good Python API for internal data access. There is the possibility to access objects and their properties: meshes, texture coordinates, vertex coordinates, faces, normals etc.
In the past, the Blend4Web exporter had been using Python API to access and export the data of 3D models. However, Python did not have required performance and flexibility in terms of mesh data access. As a result, the Blend4Web developers had to reject Python in favor of C. The whole mesh data access code has been rewritten in C, which resulted in much more compact and faster Python API.
The purpose of this draft is to suggest a fast method for transferring the mesh data to a simple format for further serialization and export. The proposed Python module can be used by any exporters.
Definitions
In OpenGL 2+ and DirectX 9+, a batch of geometry is rendered in a single draw call. This way only a single shader (which corresponds to the Blender material) can be set up in a time. On the other hand, Blender's meshes can have more then one material.
To reflect this fact, we would like to introduce a concept of submesh - a part of the mesh to which a single material is assigned. This way, any mesh which has more than one material is divided into submeshes. Submesh data can be optimized and serialized for use in external engines.
Problems to Resolve
- Retrieving submesh data
- Submesh optimization
Proposed Python API
submesh = object.data.get_submesh(format = 'TRIANGLES', matid=mid, \
weld = True, uv=['uv1','uv2'], request = ['TANGENT', 'NORMAL', \
'VGROUPS'...], custom_in={'key1':{'DATA':[...], 'MAPPING': 'LOOP'}})
format - data format, can be TRIANGLES or POLYGONS
matid - material identifier
weld - optimize the vertices count by welding (see welding)
uv - the list of UV identifiers that may be required during submesh retrieval
request - the list of data types to retrieve; 'POSITION', 'INDICES' will be in the submesh struct even if they are not present in this list
custom_in - custom user data (see welding); this data is ordered according to the 'MAPPING' field; 'MAPPING' can be 'LOOP', 'VERTEX' or 'POLYGON'
Output Data Format (Submesh Structure)
{
'FORMAT': format,
'POSITION': [float_data],
'INDICES': [int_data],
'POLYLEN': [int_data],
'TEXCO': [{'uv1':[float_data], 'uv2':[float_data]}, ...],
'TANGENT': [{'uv1':[float_data], 'uv2':[float_data]}, ...],
'VGROUPS': [{'vg1':[float_data], 'vg2':[float_data]}, ...],
'COLOR': [{'col1':[float_data], 'col2':[float_data]}, ...],
'NORMAL': [float_data],
'CUSTOM': {'custom1':{'DATA':[...], 'MAPPING':mapping}, 'custom2':..., ...}
}
FORMAT - data format; possible values: 'TRIANGLES' or 'POLYGONS'
POSITION - vertex coordinates, plain array of (x,y,z) of float type
INDICES - triangles/polygons indices of int type
POLYLEN - polygon vertices count; if the value of the 'FORMAT' field is 'TRIANGLES' then this field may not be present and is defaulted to 3
TEXCO - texture coordinates; named plain arrays of (u, v) of float type
VGROUPS - vertex groups; named plain arrays of weights of float type
COLOR - vertex color; named plain arrays of (r, g, b) of float type
TANGENT - tangent space description; named plain arrays of (T.x, T.y, T.z, Sign) of float type
NORMAL - normal; plain array of (n.x, n.y, n.z) of float type
CUSTOM - custom output data; has order according to 'FORMAT'
Submesh Welding
We call submesh non-optimized if it is possible to represent it by the lesser amount of data, primarily, by the lesser count of vertices.
Under specific conditions, such as equality of positions, normals etc., we can assume that the vertices are identical and 'weld' them into a single vertex. Thus, the total number of vertices is decreased, which leads to memory savings and increased performance.
Custom Data
In addition to the standard fields, there is also a 'CUSTOM' field in the submesh structure. Correspondingly, the 'custom_in' parameter is present in the 'get_submesh' function written in the same format.
'MAPPING' defines 'DATA' elements order. On the C side, each 'CUSTOM' element is interpreted as a byte-array; the length of the element will be calculated automatically.
Welding processes the 'CUSTOM' data in the same way as the standard fields such as 'NORMAL'.
Serialization
Retrieved data can be processed in Python, because it is essentially not a raw data but the typed arrays.
Architecture-independent serialization can be implemented for each field accordingly to the data type (see [[1]]