Merge pull request #1 from facebookincubator/master
update host master version
This commit is contained in:
commit
9b21de2ca1
|
@ -8,6 +8,8 @@ a modern runtime asset delivery format.
|
|||
Precompiled binaries releases for Windows, Mac OS X and Linux may be
|
||||
found [here](https://github.com/facebookincubator/FBX2glTF/releases).
|
||||
|
||||
Bleeding-edge binaries are periodically built and publicly available [here](https://dev.azure.com/parwinzell/FBX2glTF/): click a build (usually the most recent), then the 'Artefacts' dropdown in the upper right.
|
||||
|
||||
## Running
|
||||
|
||||
The tool can be invoked like so:
|
||||
|
|
|
@ -1,76 +1,80 @@
|
|||
import { readFileSync } from 'fs';
|
||||
import * as tmp from 'tmp';
|
||||
import * as path from 'path';
|
||||
import {assert, expect} from 'chai';
|
||||
import * as fbx2gltf from 'fbx2gltf';
|
||||
import { assert, expect } from 'chai';
|
||||
import { validateBytes } from 'gltf-validator';
|
||||
import {readFileSync} from 'fs';
|
||||
import {validateBytes} from 'gltf-validator';
|
||||
import * as path from 'path';
|
||||
import * as tmp from 'tmp';
|
||||
|
||||
interface Model {
|
||||
path: string;
|
||||
ignoredIssues?: Array<string>;
|
||||
args?: Array<string>;
|
||||
path: string;
|
||||
ignoredIssues?: Array<string>;
|
||||
args?: Array<string>;
|
||||
}
|
||||
|
||||
const MODELS :Array<Model> = [
|
||||
{ path: 'fromFacebook/Jon/jon_morph' },
|
||||
{
|
||||
path: 'fromFacebook/Jon/troll-final',
|
||||
ignoredIssues: [ 'ACCESSOR_NON_UNIT' ],
|
||||
},
|
||||
{ path: 'fromFacebook/Natalie/GlitchRobot' },
|
||||
{ path: 'fromFacebook/Ocean/blackvan/blackvan_with_windows' },
|
||||
{ path: 'fromFacebook/Ocean/zell_van_vertex_color' },
|
||||
{ path: 'fromFacebook/RAZ/RAZ_ape' },
|
||||
{ path: 'fromFbxSDK/Box' },
|
||||
{
|
||||
path: 'fromFbxSDK/Humanoid',
|
||||
ignoredIssues: [ 'UNSUPPORTED_EXTENSION' ],
|
||||
},
|
||||
{
|
||||
path: 'fromFbxSDK/Camera',
|
||||
ignoredIssues: [ 'UNSUPPORTED_EXTENSION' ],
|
||||
},
|
||||
{ path: 'fromFbxSDK/Normals' },
|
||||
{ path: 'fromGltfSamples/BoxVertexColors/BoxVertexColors' },
|
||||
{ path: 'fromGltfSamples/WaterBottle/NewWaterBottle' },
|
||||
const MODELS: Array<Model> = [
|
||||
{path : 'fromFacebook/Jon/jon_morph'},
|
||||
{
|
||||
path : 'fromFacebook/Jon/troll-final',
|
||||
ignoredIssues : [ 'ACCESSOR_NON_UNIT' ],
|
||||
},
|
||||
{path : 'fromFacebook/Natalie/GlitchRobot'},
|
||||
{path : 'fromFacebook/Ocean/blackvan/blackvan_with_windows'},
|
||||
{
|
||||
path : 'fromFacebook/Ocean/zell_van_vertex_color',
|
||||
args : [ '--draco' ],
|
||||
ignoredIssues : [ 'UNSUPPORTED_EXTENSION' ],
|
||||
},
|
||||
{path : 'fromFacebook/RAZ/RAZ_ape', args : [ '--long-indices=always' ]},
|
||||
{path : 'fromFbxSDK/Box'},
|
||||
{
|
||||
path : 'fromFbxSDK/Humanoid',
|
||||
ignoredIssues : [ 'UNSUPPORTED_EXTENSION' ],
|
||||
},
|
||||
{
|
||||
path : 'fromFbxSDK/Camera',
|
||||
ignoredIssues : [ 'UNSUPPORTED_EXTENSION' ],
|
||||
},
|
||||
{path : 'fromFbxSDK/Normals'},
|
||||
{path : 'fromGltfSamples/BoxVertexColors/BoxVertexColors', args : [ '--khr-materials-unlit' ]},
|
||||
{path : 'fromGltfSamples/WaterBottle/NewWaterBottle'},
|
||||
];
|
||||
|
||||
const CONVERSION_TIMEOUT_MS = 50000;
|
||||
|
||||
describe('FBX2glTF', () => {
|
||||
const tmpobj = tmp.dirSync();
|
||||
for(let model of MODELS) {
|
||||
const modelName = path.basename(model.path);
|
||||
describe('Model: ' + modelName, () => {
|
||||
const fbxPath = path.join('models', model.path + '.fbx');
|
||||
let glbBytes;
|
||||
it('should convert fbx to glb', async () => {
|
||||
const glbPath = path.join(tmpobj.name, modelName + '.glb');
|
||||
const tmpobj = tmp.dirSync();
|
||||
for (let model of MODELS) {
|
||||
const modelName = path.basename(model.path);
|
||||
describe('Model: ' + modelName, () => {
|
||||
const fbxPath = path.join('models', model.path + '.fbx');
|
||||
let glbBytes;
|
||||
it('should convert fbx to glb', async () => {
|
||||
const glbPath = path.join(tmpobj.name, modelName + '.glb');
|
||||
|
||||
try {
|
||||
const destPath = await fbx2gltf(fbxPath, glbPath, model.args || []);
|
||||
assert.isNotNull(destPath);
|
||||
glbBytes = readFileSync(destPath);
|
||||
} catch (err) {
|
||||
throw new Error('Conversion failed: ' + err);
|
||||
}
|
||||
}).timeout(CONVERSION_TIMEOUT_MS);
|
||||
try {
|
||||
const destPath = await fbx2gltf(fbxPath, glbPath, model.args || []);
|
||||
assert.isNotNull(destPath);
|
||||
glbBytes = readFileSync(destPath);
|
||||
} catch (err) {
|
||||
throw new Error('Conversion failed: ' + err);
|
||||
}
|
||||
}).timeout(CONVERSION_TIMEOUT_MS);
|
||||
|
||||
it('resulting glb should be valid', async() => {
|
||||
try {
|
||||
let options = <any>{};
|
||||
if (model.ignoredIssues) {
|
||||
options.ignoredIssues = model.ignoredIssues;
|
||||
}
|
||||
const report = await validateBytes(glbBytes, options);
|
||||
expect(report.issues.numErrors).to.equal(0);
|
||||
expect(report.issues.numWarnings).to.equal(0);
|
||||
it('resulting glb should be valid', async () => {
|
||||
try {
|
||||
let options = <any>{};
|
||||
if (model.ignoredIssues) {
|
||||
options.ignoredIssues = model.ignoredIssues;
|
||||
}
|
||||
const report = await validateBytes(glbBytes, options);
|
||||
expect(report.issues.numErrors).to.equal(0);
|
||||
expect(report.issues.numWarnings).to.equal(0);
|
||||
|
||||
} catch (err) {
|
||||
throw new Error('Validation failed: ' + err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
console.log('GLB files may be inspected in: ' + tmpobj.name);
|
||||
} catch (err) {
|
||||
throw new Error('Validation failed: ' + err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
console.log('GLB files may be inspected in: ' + tmpobj.name);
|
||||
});
|
||||
|
|
|
@ -209,9 +209,11 @@ static void ReadMesh(
|
|||
|
||||
std::shared_ptr<RawMatProps> rawMatProps;
|
||||
FbxString materialName;
|
||||
long materialId;
|
||||
|
||||
if (fbxMaterial == nullptr) {
|
||||
materialName = "DefaultMaterial";
|
||||
materialId = -1;
|
||||
rawMatProps.reset(new RawTraditionalMatProps(
|
||||
RAW_SHADING_MODEL_LAMBERT,
|
||||
Vec3f(0, 0, 0),
|
||||
|
@ -222,6 +224,7 @@ static void ReadMesh(
|
|||
|
||||
} else {
|
||||
materialName = fbxMaterial->name;
|
||||
materialId = fbxMaterial->id;
|
||||
|
||||
const auto maybeAddTexture = [&](const FbxFileTexture* tex, RawTextureUsage usage) {
|
||||
if (tex != nullptr) {
|
||||
|
@ -436,8 +439,8 @@ static void ReadMesh(
|
|||
|
||||
const RawMaterialType materialType =
|
||||
GetMaterialType(raw, textures, vertexTransparency, skinning.IsSkinned());
|
||||
const int rawMaterialIndex =
|
||||
raw.AddMaterial(materialName, materialType, textures, rawMatProps, userProperties);
|
||||
const int rawMaterialIndex = raw.AddMaterial(
|
||||
materialId, materialName, materialType, textures, rawMatProps, userProperties);
|
||||
|
||||
raw.AddTriangle(
|
||||
rawVertexIndices[0],
|
||||
|
|
|
@ -149,6 +149,7 @@ std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::reso
|
|||
}
|
||||
|
||||
std::unique_ptr<FbxRoughMetMaterialInfo> res(new FbxRoughMetMaterialInfo(
|
||||
fbxMaterial->GetUniqueID(),
|
||||
fbxMaterial->GetName(),
|
||||
FbxRoughMetMaterialInfo::FBX_SHADER_METROUGH,
|
||||
baseCol,
|
||||
|
|
|
@ -16,9 +16,10 @@
|
|||
|
||||
class FbxMaterialInfo {
|
||||
public:
|
||||
FbxMaterialInfo(const FbxString& name, const FbxString& shadingModel)
|
||||
: name(name), shadingModel(shadingModel) {}
|
||||
FbxMaterialInfo(const FbxUInt64 id, const FbxString& name, const FbxString& shadingModel)
|
||||
: id(id), name(name), shadingModel(shadingModel) {}
|
||||
|
||||
const FbxUInt64 id;
|
||||
const FbxString name;
|
||||
const FbxString shadingModel;
|
||||
};
|
||||
|
|
|
@ -21,12 +21,13 @@ struct FbxRoughMetMaterialInfo : FbxMaterialInfo {
|
|||
const std::map<const FbxTexture*, FbxString>& textureLocations);
|
||||
|
||||
FbxRoughMetMaterialInfo(
|
||||
const FbxUInt64 id,
|
||||
const FbxString& name,
|
||||
const FbxString& shadingModel,
|
||||
FbxDouble4 baseColor,
|
||||
FbxDouble metallic,
|
||||
FbxDouble roughness)
|
||||
: FbxMaterialInfo(name, shadingModel),
|
||||
: FbxMaterialInfo(id, name, shadingModel),
|
||||
baseColor(baseColor),
|
||||
metallic(metallic),
|
||||
roughness(roughness) {}
|
||||
|
|
|
@ -54,6 +54,7 @@ std::unique_ptr<FbxRoughMetMaterialInfo> FbxStingrayPBSMaterialResolver::resolve
|
|||
|
||||
FbxDouble3 baseColor = getVec("base_color");
|
||||
std::unique_ptr<FbxRoughMetMaterialInfo> res(new FbxRoughMetMaterialInfo(
|
||||
fbxMaterial->GetUniqueID(),
|
||||
fbxMaterial->GetName(),
|
||||
FbxRoughMetMaterialInfo::FBX_SHADER_METROUGH,
|
||||
FbxDouble4(baseColor[0], baseColor[1], baseColor[2], 1),
|
||||
|
|
|
@ -68,8 +68,8 @@ std::unique_ptr<FbxTraditionalMaterialInfo> FbxTraditionalMaterialResolver::reso
|
|||
};
|
||||
|
||||
std::string name = fbxMaterial->GetName();
|
||||
std::unique_ptr<FbxTraditionalMaterialInfo> res(
|
||||
new FbxTraditionalMaterialInfo(name.c_str(), fbxMaterial->ShadingModel.Get()));
|
||||
std::unique_ptr<FbxTraditionalMaterialInfo> res(new FbxTraditionalMaterialInfo(
|
||||
fbxMaterial->GetUniqueID(), name.c_str(), fbxMaterial->ShadingModel.Get()));
|
||||
|
||||
// four properties are on the same structure and follow the same rules
|
||||
auto handleBasicProperty = [&](const char* colName,
|
||||
|
|
|
@ -14,8 +14,11 @@ struct FbxTraditionalMaterialInfo : FbxMaterialInfo {
|
|||
static constexpr const char* FBX_SHADER_BLINN = "Blinn";
|
||||
static constexpr const char* FBX_SHADER_PHONG = "Phong";
|
||||
|
||||
FbxTraditionalMaterialInfo(const FbxString& name, const FbxString& shadingModel)
|
||||
: FbxMaterialInfo(name, shadingModel) {}
|
||||
FbxTraditionalMaterialInfo(
|
||||
const FbxUInt64 id,
|
||||
const FbxString& name,
|
||||
const FbxString& shadingModel)
|
||||
: FbxMaterialInfo(id, name, shadingModel) {}
|
||||
|
||||
FbxFileTexture* texAmbient{};
|
||||
FbxVector4 colAmbient{};
|
||||
|
|
|
@ -77,11 +77,6 @@ static const std::vector<TriangleIndex> getIndexArray(const RawModel& raw) {
|
|||
return result;
|
||||
}
|
||||
|
||||
// TODO: replace with a proper MaterialHasher class
|
||||
static const std::string materialHash(const RawMaterial& m) {
|
||||
return m.name + "_" + std::to_string(m.type);
|
||||
}
|
||||
|
||||
ModelData* Raw2Gltf(
|
||||
std::ofstream& gltfOutStream,
|
||||
const std::string& outputFolder,
|
||||
|
@ -123,7 +118,7 @@ ModelData* Raw2Gltf(
|
|||
std::unique_ptr<GltfModel> gltf(new GltfModel(options));
|
||||
|
||||
std::map<long, std::shared_ptr<NodeData>> nodesById;
|
||||
std::map<std::string, std::shared_ptr<MaterialData>> materialsByName;
|
||||
std::map<long, std::shared_ptr<MaterialData>> materialsById;
|
||||
std::map<std::string, std::shared_ptr<TextureData>> textureByIndicesKey;
|
||||
std::map<long, std::shared_ptr<MeshData>> meshBySurfaceId;
|
||||
|
||||
|
@ -394,7 +389,8 @@ ModelData* Raw2Gltf(
|
|||
emissiveFactor * emissiveIntensity,
|
||||
khrCmnUnlitMat,
|
||||
pbrMetRough));
|
||||
materialsByName[materialHash(material)] = mData;
|
||||
fmt::printf("Stashing material of id %ls, name %s...\n", material.id, material.name.c_str());
|
||||
materialsById[material.id] = mData;
|
||||
|
||||
if (options.enableUserProperties) {
|
||||
mData->userProperties = material.userProperties;
|
||||
|
@ -408,7 +404,9 @@ ModelData* Raw2Gltf(
|
|||
|
||||
const RawMaterial& rawMaterial =
|
||||
surfaceModel.GetMaterial(surfaceModel.GetTriangle(0).materialIndex);
|
||||
const MaterialData& mData = require(materialsByName, materialHash(rawMaterial));
|
||||
fmt::printf(
|
||||
"Seeking material of id %ls, name %s...\n", rawMaterial.id, rawMaterial.name.c_str());
|
||||
const MaterialData& mData = require(materialsById, rawMaterial.id);
|
||||
|
||||
MeshData* mesh = nullptr;
|
||||
auto meshIter = meshBySurfaceId.find(surfaceId);
|
||||
|
|
|
@ -129,6 +129,7 @@ int RawModel::AddTexture(
|
|||
|
||||
int RawModel::AddMaterial(const RawMaterial& material) {
|
||||
return AddMaterial(
|
||||
material.id,
|
||||
material.name.c_str(),
|
||||
material.type,
|
||||
material.textures,
|
||||
|
@ -137,6 +138,7 @@ int RawModel::AddMaterial(const RawMaterial& material) {
|
|||
}
|
||||
|
||||
int RawModel::AddMaterial(
|
||||
const long id,
|
||||
const char* name,
|
||||
const RawMaterialType materialType,
|
||||
const int textures[RAW_TEXTURE_USAGE_MAX],
|
||||
|
@ -169,6 +171,7 @@ int RawModel::AddMaterial(
|
|||
}
|
||||
|
||||
RawMaterial material;
|
||||
material.id = id;
|
||||
material.name = name;
|
||||
material.type = materialType;
|
||||
material.info = materialInfo;
|
||||
|
|
|
@ -262,6 +262,7 @@ struct RawMetRoughMatProps : RawMatProps {
|
|||
};
|
||||
|
||||
struct RawMaterial {
|
||||
long id;
|
||||
std::string name;
|
||||
RawMaterialType type;
|
||||
std::shared_ptr<RawMatProps> info;
|
||||
|
@ -374,6 +375,7 @@ class RawModel {
|
|||
RawTextureUsage usage);
|
||||
int AddMaterial(const RawMaterial& material);
|
||||
int AddMaterial(
|
||||
const long id,
|
||||
const char* name,
|
||||
const RawMaterialType materialType,
|
||||
const int textures[RAW_TEXTURE_USAGE_MAX],
|
||||
|
|
Loading…
Reference in New Issue