mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 05:03:31 +02:00
Support vertex colours and multiple unnamed mesh materials.
# Conflicts: # libraries/fbx/src/GLTFSerializer.cpp
This commit is contained in:
parent
5bf872b1b8
commit
471baf83c6
2 changed files with 166 additions and 56 deletions
|
@ -261,6 +261,41 @@ bool GLTFSerializer::setAsset(const QJsonObject& object) {
|
||||||
return isAssetDefined;
|
return isAssetDefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLTFAccessor::GLTFAccessorSparse::GLTFAccessorSparseIndices GLTFSerializer::createAccessorSparseIndices(const QJsonObject& object) {
|
||||||
|
GLTFAccessor::GLTFAccessorSparse::GLTFAccessorSparseIndices accessorSparseIndices;
|
||||||
|
|
||||||
|
getIntVal(object, "bufferView", accessorSparseIndices.bufferView, accessorSparseIndices.defined);
|
||||||
|
getIntVal(object, "byteOffset", accessorSparseIndices.byteOffset, accessorSparseIndices.defined);
|
||||||
|
getIntVal(object, "componentType", accessorSparseIndices.componentType, accessorSparseIndices.defined);
|
||||||
|
|
||||||
|
return accessorSparseIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTFAccessor::GLTFAccessorSparse::GLTFAccessorSparseValues GLTFSerializer::createAccessorSparseValues(const QJsonObject& object) {
|
||||||
|
GLTFAccessor::GLTFAccessorSparse::GLTFAccessorSparseValues accessorSparseValues;
|
||||||
|
|
||||||
|
getIntVal(object, "bufferView", accessorSparseValues.bufferView, accessorSparseValues.defined);
|
||||||
|
getIntVal(object, "byteOffset", accessorSparseValues.byteOffset, accessorSparseValues.defined);
|
||||||
|
|
||||||
|
return accessorSparseValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTFAccessor::GLTFAccessorSparse GLTFSerializer::createAccessorSparse(const QJsonObject& object) {
|
||||||
|
GLTFAccessor::GLTFAccessorSparse accessorSparse;
|
||||||
|
|
||||||
|
getIntVal(object, "count", accessorSparse.count, accessorSparse.defined);
|
||||||
|
QJsonObject sparseIndicesObject;
|
||||||
|
if (getObjectVal(object, "indices", sparseIndicesObject, accessorSparse.defined)) {
|
||||||
|
accessorSparse.indices = createAccessorSparseIndices(sparseIndicesObject);
|
||||||
|
}
|
||||||
|
QJsonObject sparseValuesObject;
|
||||||
|
if (getObjectVal(object, "values", sparseValuesObject, accessorSparse.defined)) {
|
||||||
|
accessorSparse.values = createAccessorSparseValues(sparseValuesObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessorSparse;
|
||||||
|
}
|
||||||
|
|
||||||
bool GLTFSerializer::addAccessor(const QJsonObject& object) {
|
bool GLTFSerializer::addAccessor(const QJsonObject& object) {
|
||||||
GLTFAccessor accessor;
|
GLTFAccessor accessor;
|
||||||
|
|
||||||
|
@ -273,6 +308,12 @@ bool GLTFSerializer::addAccessor(const QJsonObject& object) {
|
||||||
if (getStringVal(object, "type", type, accessor.defined)) {
|
if (getStringVal(object, "type", type, accessor.defined)) {
|
||||||
accessor.type = getAccessorType(type);
|
accessor.type = getAccessorType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonObject sparseObject;
|
||||||
|
if (getObjectVal(object, "sparse", sparseObject, accessor.defined)) {
|
||||||
|
accessor.sparse = createAccessorSparse(sparseObject);
|
||||||
|
}
|
||||||
|
|
||||||
getDoubleArrayVal(object, "max", accessor.max, accessor.defined);
|
getDoubleArrayVal(object, "max", accessor.max, accessor.defined);
|
||||||
getDoubleArrayVal(object, "min", accessor.min, accessor.defined);
|
getDoubleArrayVal(object, "min", accessor.min, accessor.defined);
|
||||||
|
|
||||||
|
@ -919,7 +960,13 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
QString unknown = "Default";
|
QString unknown = "Default";
|
||||||
int ukcount = 0;
|
int ukcount = 0;
|
||||||
foreach(auto material, _file.materials) {
|
foreach(auto material, _file.materials) {
|
||||||
QString mid = (material.defined["name"]) ? material.name : unknown + ukcount++;
|
if (!(material.defined["name"])) {
|
||||||
|
QString name = unknown + QString::number(ukcount++);
|
||||||
|
material.name = name;
|
||||||
|
material.defined.insert("name", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString mid = material.name;
|
||||||
materialIDs.push_back(mid);
|
materialIDs.push_back(mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,6 +975,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
hfmModel.materials[matid] = HFMMaterial();
|
hfmModel.materials[matid] = HFMMaterial();
|
||||||
HFMMaterial& hfmMaterial = hfmModel.materials[matid];
|
HFMMaterial& hfmMaterial = hfmModel.materials[matid];
|
||||||
hfmMaterial._material = std::make_shared<graphics::Material>();
|
hfmMaterial._material = std::make_shared<graphics::Material>();
|
||||||
|
hfmMaterial.name = hfmMaterial.materialID = matid;
|
||||||
setHFMMaterial(hfmMaterial, _file.materials[i]);
|
setHFMMaterial(hfmMaterial, _file.materials[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,7 +986,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
auto& node = _file.nodes[nodeIndex];
|
auto& node = _file.nodes[nodeIndex];
|
||||||
|
|
||||||
if (node.defined["mesh"]) {
|
if (node.defined["mesh"]) {
|
||||||
foreach(auto &primitive, _file.meshes[node.mesh].primitives) {
|
|
||||||
hfmModel.meshes.append(HFMMesh());
|
hfmModel.meshes.append(HFMMesh());
|
||||||
HFMMesh& mesh = hfmModel.meshes[hfmModel.meshes.size() - 1];
|
HFMMesh& mesh = hfmModel.meshes[hfmModel.meshes.size() - 1];
|
||||||
if (!hfmModel.hasSkeletonJoints) {
|
if (!hfmModel.hasSkeletonJoints) {
|
||||||
|
@ -962,6 +1010,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
root.inverseBindTransform = Transform(root.inverseBindMatrix);
|
root.inverseBindTransform = Transform(root.inverseBindMatrix);
|
||||||
mesh.clusters.append(root);
|
mesh.clusters.append(root);
|
||||||
|
|
||||||
|
foreach(auto &primitive, _file.meshes[node.mesh].primitives) {
|
||||||
HFMMeshPart part = HFMMeshPart();
|
HFMMeshPart part = HFMMeshPart();
|
||||||
|
|
||||||
int indicesAccessorIdx = primitive.indices;
|
int indicesAccessorIdx = primitive.indices;
|
||||||
|
@ -972,10 +1021,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
|
|
||||||
int indicesAccBoffset = indicesAccessor.defined["byteOffset"] ? indicesAccessor.byteOffset : 0;
|
int indicesAccBoffset = indicesAccessor.defined["byteOffset"] ? indicesAccessor.byteOffset : 0;
|
||||||
|
|
||||||
QVector<int> raw_indices;
|
|
||||||
QVector<glm::vec3> raw_vertices;
|
|
||||||
QVector<glm::vec3> raw_normals;
|
|
||||||
|
|
||||||
bool success = addArrayOfType(indicesBuffer.blob,
|
bool success = addArrayOfType(indicesBuffer.blob,
|
||||||
indicesBufferview.byteOffset + indicesAccBoffset,
|
indicesBufferview.byteOffset + indicesAccBoffset,
|
||||||
indicesAccessor.count,
|
indicesAccessor.count,
|
||||||
|
@ -988,6 +1033,14 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increment the triangle indices by the current mesh vertex count so each mesh part can all reference the same buffers within the mesh
|
||||||
|
int prevMeshVerticesCount = mesh.vertices.count();
|
||||||
|
if (prevMeshVerticesCount > 0) {
|
||||||
|
for (int i = 0; i < part.triangleIndices.count(); i++) {
|
||||||
|
part.triangleIndices[i] += prevMeshVerticesCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QList<QString> keys = primitive.attributes.values.keys();
|
QList<QString> keys = primitive.attributes.values.keys();
|
||||||
QVector<uint16_t> clusterJoints;
|
QVector<uint16_t> clusterJoints;
|
||||||
QVector<float> clusterWeights;
|
QVector<float> clusterWeights;
|
||||||
|
@ -1029,22 +1082,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
for (int n = 0; n < normals.size(); n = n + 3) {
|
for (int n = 0; n < normals.size(); n = n + 3) {
|
||||||
mesh.normals.push_back(glm::vec3(normals[n], normals[n + 1], normals[n + 2]));
|
mesh.normals.push_back(glm::vec3(normals[n], normals[n + 1], normals[n + 2]));
|
||||||
}
|
}
|
||||||
} else if (key == "COLOR_0") {
|
|
||||||
QVector<float> colors;
|
|
||||||
success = addArrayOfType(buffer.blob,
|
|
||||||
bufferview.byteOffset + accBoffset,
|
|
||||||
accessor.count,
|
|
||||||
colors,
|
|
||||||
accessor.type,
|
|
||||||
accessor.componentType);
|
|
||||||
if (!success) {
|
|
||||||
qWarning(modelformat) << "There was a problem reading glTF COLOR_0 data for model " << _url;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int stride = (accessor.type == GLTFAccessorType::VEC4) ? 4 : 3;
|
|
||||||
for (int n = 0; n < colors.size() - 3; n += stride) {
|
|
||||||
mesh.colors.push_back(glm::vec3(colors[n], colors[n + 1], colors[n + 2]));
|
|
||||||
}
|
|
||||||
} else if (key == "TANGENT") {
|
} else if (key == "TANGENT") {
|
||||||
QVector<float> tangents;
|
QVector<float> tangents;
|
||||||
success = addArrayOfType(buffer.blob,
|
success = addArrayOfType(buffer.blob,
|
||||||
|
@ -1092,6 +1129,22 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
}
|
}
|
||||||
for (int n = 0; n < texcoords.size(); n = n + 2) {
|
for (int n = 0; n < texcoords.size(); n = n + 2) {
|
||||||
mesh.texCoords1.push_back(glm::vec2(texcoords[n], texcoords[n + 1]));
|
mesh.texCoords1.push_back(glm::vec2(texcoords[n], texcoords[n + 1]));
|
||||||
|
}
|
||||||
|
} else if (key == "COLOR_0") {
|
||||||
|
QVector<float> colors;
|
||||||
|
success = addArrayOfType(buffer.blob,
|
||||||
|
bufferview.byteOffset + accBoffset,
|
||||||
|
accessor.count,
|
||||||
|
colors,
|
||||||
|
accessor.type,
|
||||||
|
accessor.componentType);
|
||||||
|
if (!success) {
|
||||||
|
qWarning(modelformat) << "There was a problem reading glTF COLOR_0 data for model " << _url;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int stride = (accessor.type == GLTFAccessorType::VEC4) ? 4 : 3;
|
||||||
|
for (int n = 0; n < colors.size() - 3; n += stride) {
|
||||||
|
mesh.colors.push_back(glm::vec3(colors[n], colors[n + 1], colors[n + 2]));
|
||||||
}
|
}
|
||||||
} else if (key == "JOINTS_0") {
|
} else if (key == "JOINTS_0") {
|
||||||
QVector<uint16_t> joints;
|
QVector<uint16_t> joints;
|
||||||
|
@ -1251,6 +1304,14 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
||||||
|
|
||||||
mesh.meshIndex = hfmModel.meshes.size();
|
mesh.meshIndex = hfmModel.meshes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mesh.meshExtents.reset();
|
||||||
|
foreach(const glm::vec3& vertex, mesh.vertices) {
|
||||||
|
mesh.meshExtents.addPoint(vertex);
|
||||||
|
hfmModel.meshExtents.addPoint(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh.meshIndex = hfmModel.meshes.size();
|
||||||
}
|
}
|
||||||
nodecount++;
|
nodecount++;
|
||||||
}
|
}
|
||||||
|
@ -1404,10 +1465,6 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) {
|
||||||
void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) {
|
void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) {
|
||||||
|
|
||||||
|
|
||||||
if (material.defined["name"]) {
|
|
||||||
fbxmat.name = fbxmat.materialID = material.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (material.defined["emissiveFactor"] && material.emissiveFactor.size() == 3) {
|
if (material.defined["emissiveFactor"] && material.emissiveFactor.size() == 3) {
|
||||||
glm::vec3 emissive = glm::vec3(material.emissiveFactor[0],
|
glm::vec3 emissive = glm::vec3(material.emissiveFactor[0],
|
||||||
material.emissiveFactor[1],
|
material.emissiveFactor[1],
|
||||||
|
|
|
@ -481,6 +481,49 @@ namespace GLTFAccessorComponentType {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
struct GLTFAccessor {
|
struct GLTFAccessor {
|
||||||
|
struct GLTFAccessorSparse {
|
||||||
|
struct GLTFAccessorSparseIndices {
|
||||||
|
int bufferView;
|
||||||
|
int byteOffset{ 0 };
|
||||||
|
int componentType;
|
||||||
|
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["bufferView"]) {
|
||||||
|
qCDebug(modelformat) << "bufferView: " << bufferView;
|
||||||
|
}
|
||||||
|
if (defined["byteOffset"]) {
|
||||||
|
qCDebug(modelformat) << "byteOffset: " << byteOffset;
|
||||||
|
}
|
||||||
|
if (defined["componentType"]) {
|
||||||
|
qCDebug(modelformat) << "componentType: " << componentType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct GLTFAccessorSparseValues {
|
||||||
|
int bufferView;
|
||||||
|
int byteOffset{ 0 };
|
||||||
|
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["bufferView"]) {
|
||||||
|
qCDebug(modelformat) << "bufferView: " << bufferView;
|
||||||
|
}
|
||||||
|
if (defined["byteOffset"]) {
|
||||||
|
qCDebug(modelformat) << "byteOffset: " << byteOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int count;
|
||||||
|
GLTFAccessorSparseIndices indices;
|
||||||
|
GLTFAccessorSparseValues values;
|
||||||
|
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
int bufferView;
|
int bufferView;
|
||||||
int byteOffset { 0 };
|
int byteOffset { 0 };
|
||||||
int componentType; //required
|
int componentType; //required
|
||||||
|
@ -489,6 +532,7 @@ struct GLTFAccessor {
|
||||||
bool normalized{ false };
|
bool normalized{ false };
|
||||||
QVector<double> max;
|
QVector<double> max;
|
||||||
QVector<double> min;
|
QVector<double> min;
|
||||||
|
GLTFAccessorSparse sparse;
|
||||||
QMap<QString, bool> defined;
|
QMap<QString, bool> defined;
|
||||||
void dump() {
|
void dump() {
|
||||||
if (defined["bufferView"]) {
|
if (defined["bufferView"]) {
|
||||||
|
@ -521,6 +565,10 @@ struct GLTFAccessor {
|
||||||
qCDebug(modelformat) << m;
|
qCDebug(modelformat) << m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (defined["sparse"]) {
|
||||||
|
qCDebug(modelformat) << "sparse: ";
|
||||||
|
sparse.dump();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -763,6 +811,11 @@ private:
|
||||||
int& outidx, QMap<QString, bool>& defined);
|
int& outidx, QMap<QString, bool>& defined);
|
||||||
|
|
||||||
bool setAsset(const QJsonObject& object);
|
bool setAsset(const QJsonObject& object);
|
||||||
|
|
||||||
|
GLTFAccessor::GLTFAccessorSparse::GLTFAccessorSparseIndices createAccessorSparseIndices(const QJsonObject& object);
|
||||||
|
GLTFAccessor::GLTFAccessorSparse::GLTFAccessorSparseValues createAccessorSparseValues(const QJsonObject& object);
|
||||||
|
GLTFAccessor::GLTFAccessorSparse createAccessorSparse(const QJsonObject& object);
|
||||||
|
|
||||||
bool addAccessor(const QJsonObject& object);
|
bool addAccessor(const QJsonObject& object);
|
||||||
bool addAnimation(const QJsonObject& object);
|
bool addAnimation(const QJsonObject& object);
|
||||||
bool addBufferView(const QJsonObject& object);
|
bool addBufferView(const QJsonObject& object);
|
||||||
|
|
Loading…
Reference in a new issue