At the glTF level, transparency is a scalar; we just throw away any
color information in FBX TransparentColor. We still need to calculate
our total opacity from it, however. This is the right formula, which
additionally matches the deprecated (but still populated, by the Maya
exporter) 'Opacity' property.
This adds blend shape / morph target functionality.
At the FBX level, a mesh can have a number of deformers associated with it. One such deformer type is the blend shape. A blend shape is a collection of channels, which do all the work. A channel can consist of a single target shape (the simple case) or multiple (a progressive morph). In the latter case, the artist has created in-between shapes, the assumption being that linear interpolation between a beginning shape and an end shape would be too crude. Each such target shape contains a complete set of new positions for each vertex of the deformed base mesh.
(It's also supposed to be optionally a complete set of normals and tangents, but I've yet to see that work right; they always come through as zeroes. This is something to investigate in the future.)
So the number of glTF morph targets in a mesh is the total number of FBX target shapes associated with channels associated with blend shape deformers associated with that mesh! Yikes.
The per-vertex data of each such target shape is added to a vector in RawVertex. A side effect of this is that vertices that participate in blend shapes must be made unique to the mesh in question, as opposed to general vertices which are shared across multiple surfaces.
Blend Shape based animations become identical glTF morph target animations..
Fixes#17.
Lean on the excellent pre-existing support for creating multiple glTF
meshes from a single FBX mesh based on material type. All the triangles
with (at least one) non-opaque vertex get flagged as transparent
material. They will all go separately in their own mesh after the
CreateMaterialModels() gauntlet.
Fixes#25.
We were warnings against eInheritRSrs, which is actually the one type of
ineritance we're good with. It's eInheritRrSs we should freak out about.
That said, no need to do it for the root node -- at that point there is
no global transform to worry about.
When we convert a file that's in our CWD, on Unix the folder component
of the path will simply be "", whereas opendir() wants ".".
I want to take another more substantial pass at texture resolution, once
we're out of urgent bugfix mode.
Some FBX files have index arrays that contain -1 (indeed, that are
nothing but negative ones). Presumably the intention is to specify "no
material". In any case, let's not segfault.
When we've successfully located a referenced texture image on the local
filesystem and we're generating non-binary, non-embedded output, copy
the source folder wholesale into the destination directory.
This means the output folder is always a full, free-standing deployment,
one that can be dragged into e.g. https://gltf-viewer.donmccurdy.com/
In the FBX world, (0, 0) is generally the lower left. By the glTF
specification, (0, 0) is the upper left. The only recourse is to
literally flip all texture files (generally unwise) or to remap the UV
space.
Is this confusing in an artist-to-engineer workflow? Maybe. But it's the
best option, and it seems reasonably easy to communicate.
To request unflipped coordinates, send in a --no-flip-v command switch.
* Further improvemens to texture resolution.
- Move towards std::string over char * and FbxString where convenient,
- Make a clear distinction between textures whose image files have been
located and those who haven't; warn early in the latter case.
- Extend RawTexture so we always know logical name in FBX, original file
name in FBX, and inferred location in local filesystem.
- In non-binary mode, simply output the inferred local file basename as
the URI; this will be the correct relative path as long as the texture
files are located next to the .gltf and .bin files.
Primary remaining urge for a follow-up PR:
- We should be copying texture image files into the .gltf output folder,
but before that we should switch to an off-the-shelf cross-platform
file manipulation library like https://github.com/cginternals/cppfs.
When we make that transition, all this texture resolution code will
undergo another refactoring.
- Removed the shell scripts. We now invoke everything straight from Node.
- Allow passing command line arguments to the tool via the Node API.
- Require .glb or .gltf extension because the tool is automatically going to
add that extension anyway, so we strip it off and add it back to shield the
user from this weirdness. The tool may eventually stop adding an extension
(and perhaps just validate it) and we can simplify our code.
- Automatically add --binary option if the requested target file is a .glb.
This also renames the bin/Windows directory to bin/Windows_NT, which is
unfortunate but that matches os.type(). This ultimately comes from uname and
that's what Windows chose to return. Let's just live with this historical
accident rather than try to paper over it.
It is not uncommon for multiple logical textures in an FBX to reference
the same filename. Each such filename should yield one buffer view only,
and all sharing textures should reference it.
- alphaMode is only BLEND for transparent materials.
- We use RawMaterial.type to figure out what's transparent.
- FBX TransparencyFactor is not opacity, but 1.0-opacity.
- Treat vertex coloured materials as transparent
- We should at least iterate over vertices here and see if any of them
actually are transparent
- Sort triangles properly: transparent ones render last!
- Nix GetFileFolder(). It was not helping. Always search for textures
- near the FBX file.
- Use RawTexture::name for the texture name and ::fileName for the
inferred local filename path.
Digging the property values and texture shadows thereof, associated with
a certain FbxSurfaceTexture, should clearly happen once per material,
not per polygon. Furthermore there is a pre-existing pattern of
Fbx-specific accessclasses in Fbx2Raw that we should follow.
Soon we'll be extracting more than Phong/Lambert properties here, and
then we'll need to do further refactoring.
We were mapping v to -v rather than 1-v, with fairly catastrophic
results. While fixing, take the trouble to introduce a more general
transformation mechanism than just an affine matrix.