-
Notifications
You must be signed in to change notification settings - Fork 331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modify FBX2glTF to allow that several nodes share the same mesh. #46
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -231,6 +231,15 @@ T &require(std::map<std::string, std::shared_ptr<T>> map, std::string key) | |
return result; | ||
} | ||
|
||
template<typename T> | ||
T &require(std::map<long, std::shared_ptr<T>> map, long key) | ||
{ | ||
auto iter = map.find(key); | ||
assert(iter != map.end()); | ||
T &result = *iter->second; | ||
return result; | ||
} | ||
|
||
static const std::vector<TriangleIndex> getIndexArray(const RawModel &raw) | ||
{ | ||
std::vector<TriangleIndex> result; | ||
|
@@ -284,7 +293,7 @@ ModelData *Raw2Gltf( | |
|
||
std::map<std::string, std::shared_ptr<NodeData>> nodesByName; | ||
std::map<std::string, std::shared_ptr<MaterialData>> materialsByName; | ||
std::map<std::string, std::shared_ptr<MeshData>> meshByNodeName; | ||
std::map<long, std::shared_ptr<MeshData>> meshBySurfaceId; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you fix up the indentation here (and anywhere else)? |
||
|
||
// for now, we only have one buffer; data->binary points to the same vector as that BufferData does. | ||
BufferData &buffer = *gltf->buffers.hold( | ||
|
@@ -461,17 +470,6 @@ ModelData *Raw2Gltf( | |
materialsByName[materialHash(material)] = mData; | ||
} | ||
|
||
// | ||
// surfaces | ||
// | ||
|
||
// in GLTF 2.0, the structural limitation is that a node can | ||
// only belong to a single mesh. A mesh can however contain any | ||
// number of primitives, which are essentially little meshes. | ||
// | ||
// so each RawSurface turns into a primitive, and we sort them | ||
// by root node using this map; one mesh per node. | ||
|
||
for (size_t surfaceIndex = 0; surfaceIndex < materialModels.size(); surfaceIndex++) { | ||
const RawModel &surfaceModel = materialModels[surfaceIndex]; | ||
|
||
|
@@ -481,50 +479,25 @@ ModelData *Raw2Gltf( | |
const RawMaterial &rawMaterial = surfaceModel.GetMaterial(surfaceModel.GetTriangle(0).materialIndex); | ||
const MaterialData &mData = require(materialsByName, materialHash(rawMaterial)); | ||
|
||
std::string nodeName = rawSurface.nodeName; | ||
NodeData &meshNode = require(nodesByName, nodeName); | ||
int surfaceId = rawSurface.id; | ||
//NodeData &meshNode = require(nodesByName, nodeName); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not leave commented-out code -- just nuke the line. |
||
|
||
MeshData *mesh = nullptr; | ||
auto meshIter = meshByNodeName.find(nodeName); | ||
if (meshIter != meshByNodeName.end()) { | ||
MeshData *mesh = nullptr; | ||
auto meshIter = meshBySurfaceId.find(surfaceId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indentation |
||
if (meshIter != meshBySurfaceId.end()) { | ||
mesh = meshIter->second.get(); | ||
|
||
} else { | ||
} | ||
else { | ||
std::vector<float> defaultDeforms; | ||
for (const auto &channel : rawSurface.blendChannels) { | ||
defaultDeforms.push_back(channel.defaultDeform); | ||
} | ||
auto meshPtr = gltf->meshes.hold(new MeshData(rawSurface.name, defaultDeforms)); | ||
meshByNodeName[nodeName] = meshPtr; | ||
meshNode.SetMesh(meshPtr->ix); | ||
meshBySurfaceId[surfaceId] = meshPtr; | ||
mesh = meshPtr.get(); | ||
} | ||
|
||
// | ||
// surface skin | ||
// | ||
if (!rawSurface.jointNames.empty()) { | ||
if (meshNode.skin == -1) { | ||
// glTF uses column-major matrices | ||
std::vector<Mat4f> inverseBindMatrices; | ||
for (const auto &inverseBindMatrice : rawSurface.inverseBindMatrices) { | ||
inverseBindMatrices.push_back(inverseBindMatrice.Transpose()); | ||
} | ||
|
||
std::vector<uint32_t> jointIndexes; | ||
for (const auto &jointName : rawSurface.jointNames) { | ||
jointIndexes.push_back(require(nodesByName, jointName).ix); | ||
} | ||
|
||
// Write out inverseBindMatrices | ||
auto accIBM = gltf->AddAccessorAndView(buffer, GLT_MAT4F, inverseBindMatrices); | ||
|
||
auto skeletonRoot = require(nodesByName, rawSurface.skeletonRootName); | ||
auto skin = *gltf->skins.hold(new SkinData(jointIndexes, *accIBM, skeletonRoot)); | ||
meshNode.SetSkin(skin.ix); | ||
} | ||
} | ||
|
||
std::shared_ptr<PrimitiveData> primitive; | ||
if (options.useDraco) { | ||
int triangleCount = surfaceModel.GetTriangleCount(); | ||
|
@@ -544,7 +517,8 @@ ModelData *Raw2Gltf( | |
AccessorData &indexes = *gltf->accessors.hold(new AccessorData(GLT_USHORT)); | ||
indexes.count = 3 * triangleCount; | ||
primitive.reset(new PrimitiveData(indexes, mData, dracoMesh)); | ||
} else { | ||
} | ||
else { | ||
const AccessorData &indexes = *gltf->AddAccessorWithView( | ||
*gltf->GetAlignedBufferView(buffer, BufferViewData::GL_ELEMENT_ARRAY_BUFFER), | ||
GLT_USHORT, getIndexArray(surfaceModel)); | ||
|
@@ -665,6 +639,53 @@ ModelData *Raw2Gltf( | |
mesh->AddPrimitive(primitive); | ||
} | ||
|
||
// | ||
// Assign meshes to node | ||
// | ||
|
||
for (int i = 0; i < raw.GetNodeCount(); i++) { | ||
|
||
const RawNode &node = raw.GetNode(i); | ||
auto nodeData = gltf->nodes.ptrs[i]; | ||
|
||
// | ||
// Assign mesh to node | ||
// | ||
if (node.surfaceId > 0) | ||
{ | ||
int surfaceIndex = raw.GetSurfaceById(node.surfaceId); | ||
const RawSurface &rawSurface = raw.GetSurface(surfaceIndex); | ||
|
||
MeshData &meshData = require(meshBySurfaceId, rawSurface.id); | ||
nodeData->SetMesh(meshData.ix); | ||
|
||
// | ||
// surface skin | ||
// | ||
if (!rawSurface.jointNames.empty()) { | ||
if (nodeData->skin == -1) { | ||
// glTF uses column-major matrices | ||
std::vector<Mat4f> inverseBindMatrices; | ||
for (const auto &inverseBindMatrice : rawSurface.inverseBindMatrices) { | ||
inverseBindMatrices.push_back(inverseBindMatrice.Transpose()); | ||
} | ||
|
||
std::vector<uint32_t> jointIndexes; | ||
for (const auto &jointName : rawSurface.jointNames) { | ||
jointIndexes.push_back(require(nodesByName, jointName).ix); | ||
} | ||
|
||
// Write out inverseBindMatrices | ||
auto accIBM = gltf->AddAccessorAndView(buffer, GLT_MAT4F, inverseBindMatrices); | ||
|
||
auto skeletonRoot = require(nodesByName, rawSurface.skeletonRootName); | ||
auto skin = *gltf->skins.hold(new SkinData(jointIndexes, *accIBM, skeletonRoot)); | ||
nodeData->SetSkin(skin.ix); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// | ||
// cameras | ||
// | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should make this available in a common header file...