mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 19:41:20 +02:00
Merge pull request #3902 from samcake/tot
Adding detection of a "hifi" global light in a FBX file used to pass information
This commit is contained in:
commit
0ad361fd60
3 changed files with 195 additions and 23 deletions
|
@ -829,28 +829,44 @@ void GeometryReader::run() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::string urlname = _url.path().toLower().toStdString();
|
if (!_reply) {
|
||||||
FBXGeometry fbxgeo;
|
throw QString("Reply is NULL ?!");
|
||||||
if (_url.path().toLower().endsWith(".svo")) {
|
|
||||||
fbxgeo = readSVO(_reply->readAll());
|
|
||||||
} else {
|
|
||||||
bool grabLightmaps = true;
|
|
||||||
float lightmapLevel = 1.0f;
|
|
||||||
// HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber...
|
|
||||||
if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) {
|
|
||||||
grabLightmaps = false;
|
|
||||||
} else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) {
|
|
||||||
lightmapLevel = 4.0f;
|
|
||||||
} else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) {
|
|
||||||
lightmapLevel = 3.5f;
|
|
||||||
}
|
|
||||||
fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel);
|
|
||||||
}
|
}
|
||||||
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo));
|
std::string urlname = _url.path().toLower().toStdString();
|
||||||
|
bool urlValid = true;
|
||||||
|
urlValid &= !urlname.empty();
|
||||||
|
urlValid &= !_url.path().isEmpty();
|
||||||
|
urlValid &= _url.path().toLower().endsWith(".fbx")
|
||||||
|
|| _url.path().toLower().endsWith(".svo");
|
||||||
|
|
||||||
|
if (urlValid) {
|
||||||
|
// Let's read the binaries from the network
|
||||||
|
QByteArray fileBinary = _reply->readAll();
|
||||||
|
if (fileBinary.isEmpty() || fileBinary.isNull()) {
|
||||||
|
throw QString("Read File binary is empty?!");
|
||||||
|
}
|
||||||
|
|
||||||
|
FBXGeometry fbxgeo;
|
||||||
|
if (_url.path().toLower().endsWith(".svo")) {
|
||||||
|
fbxgeo = readSVO(fileBinary);
|
||||||
|
} else if (_url.path().toLower().endsWith(".fbx")) {
|
||||||
|
bool grabLightmaps = true;
|
||||||
|
float lightmapLevel = 1.0f;
|
||||||
|
// HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber...
|
||||||
|
if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) {
|
||||||
|
grabLightmaps = false;
|
||||||
|
} else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) {
|
||||||
|
lightmapLevel = 4.0f;
|
||||||
|
} else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) {
|
||||||
|
lightmapLevel = 3.5f;
|
||||||
|
}
|
||||||
|
fbxgeo = readFBX(fileBinary, _mapping, grabLightmaps, lightmapLevel);
|
||||||
|
}
|
||||||
|
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo));
|
||||||
|
} else {
|
||||||
|
throw QString("url is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
// _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping)));
|
|
||||||
|
|
||||||
} catch (const QString& error) {
|
} catch (const QString& error) {
|
||||||
qDebug() << "Error reading " << _url << ": " << error;
|
qDebug() << "Error reading " << _url << ": " << error;
|
||||||
QMetaObject::invokeMethod(geometry.data(), "finishedLoading", Q_ARG(bool, false));
|
QMetaObject::invokeMethod(geometry.data(), "finishedLoading", Q_ARG(bool, false));
|
||||||
|
|
|
@ -1046,6 +1046,7 @@ FBXBlendshape extractBlendshape(const FBXNode& object) {
|
||||||
return blendshape;
|
return blendshape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setTangents(FBXMesh& mesh, int firstIndex, int secondIndex) {
|
void setTangents(FBXMesh& mesh, int firstIndex, int secondIndex) {
|
||||||
const glm::vec3& normal = mesh.normals.at(firstIndex);
|
const glm::vec3& normal = mesh.normals.at(firstIndex);
|
||||||
glm::vec3 bitangent = glm::cross(normal, mesh.vertices.at(secondIndex) - mesh.vertices.at(firstIndex));
|
glm::vec3 bitangent = glm::cross(normal, mesh.vertices.at(secondIndex) - mesh.vertices.at(firstIndex));
|
||||||
|
@ -1194,6 +1195,44 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FBXLight extractLight(const FBXNode& object) {
|
||||||
|
FBXLight light;
|
||||||
|
|
||||||
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
|
std::string childname = QString(subobject.name).toStdString();
|
||||||
|
if (subobject.name == "Properties70") {
|
||||||
|
foreach (const FBXNode& property, subobject.children) {
|
||||||
|
int valIndex = 4;
|
||||||
|
std::string propName = QString(property.name).toStdString();
|
||||||
|
if (property.name == "P") {
|
||||||
|
std::string propname = property.properties.at(0).toString().toStdString();
|
||||||
|
if (propname == "Intensity") {
|
||||||
|
light.intensity = 0.01f * property.properties.at(valIndex).value<double>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ( subobject.name == "GeometryVersion"
|
||||||
|
|| subobject.name == "TypeFlags") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
|
||||||
|
std::string type = object.properties.at(0).toString().toStdString();
|
||||||
|
type = object.properties.at(1).toString().toStdString();
|
||||||
|
type = object.properties.at(2).toString().toStdString();
|
||||||
|
|
||||||
|
foreach (const QVariant& prop, object.properties) {
|
||||||
|
std::string proptype = prop.typeName();
|
||||||
|
std::string propval = prop.toString().toStdString();
|
||||||
|
if (proptype == "Properties70") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
|
||||||
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) {
|
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) {
|
||||||
QHash<QString, ExtractedMesh> meshes;
|
QHash<QString, ExtractedMesh> meshes;
|
||||||
QHash<QString, QString> modelIDsToNames;
|
QHash<QString, QString> modelIDsToNames;
|
||||||
|
@ -1222,6 +1261,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
QHash<QString, QString> yComponents;
|
QHash<QString, QString> yComponents;
|
||||||
QHash<QString, QString> zComponents;
|
QHash<QString, QString> zComponents;
|
||||||
|
|
||||||
|
std::map<std::string, FBXLight> lights;
|
||||||
|
|
||||||
QVariantHash joints = mapping.value("joint").toHash();
|
QVariantHash joints = mapping.value("joint").toHash();
|
||||||
QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft")));
|
QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft")));
|
||||||
QString jointEyeRightName = processID(getString(joints.value("jointEyeRight", "jointEyeRight")));
|
QString jointEyeRightName = processID(getString(joints.value("jointEyeRight", "jointEyeRight")));
|
||||||
|
@ -1276,6 +1317,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
#endif
|
#endif
|
||||||
FBXGeometry geometry;
|
FBXGeometry geometry;
|
||||||
float unitScaleFactor = 1.0f;
|
float unitScaleFactor = 1.0f;
|
||||||
|
glm::vec3 ambientColor;
|
||||||
|
QString hifiGlobalNodeID;
|
||||||
foreach (const FBXNode& child, node.children) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
|
|
||||||
if (child.name == "FBXHeaderExtension") {
|
if (child.name == "FBXHeaderExtension") {
|
||||||
|
@ -1302,10 +1345,16 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
} else if (child.name == "GlobalSettings") {
|
} else if (child.name == "GlobalSettings") {
|
||||||
foreach (const FBXNode& object, child.children) {
|
foreach (const FBXNode& object, child.children) {
|
||||||
if (object.name == "Properties70") {
|
if (object.name == "Properties70") {
|
||||||
|
QString propertyName = "P";
|
||||||
|
int index = 4;
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
if (subobject.name == "P" && subobject.properties.size() >= 5 &&
|
if (subobject.name == propertyName) {
|
||||||
subobject.properties.at(0) == "UnitScaleFactor") {
|
std::string subpropName = subobject.properties.at(0).toString().toStdString();
|
||||||
unitScaleFactor = subobject.properties.at(4).toFloat();
|
if (subpropName == "UnitScaleFactor") {
|
||||||
|
unitScaleFactor = subobject.properties.at(index).toFloat();
|
||||||
|
} else if (subpropName == "AmbientColor") {
|
||||||
|
ambientColor = getVec3(subobject.properties, index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1324,6 +1373,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
QString id = getID(object.properties);
|
QString id = getID(object.properties);
|
||||||
modelIDsToNames.insert(id, name);
|
modelIDsToNames.insert(id, name);
|
||||||
|
|
||||||
|
std::string modelname = name.toLower().toStdString();
|
||||||
|
if (modelname.find("hifi") == 0) {
|
||||||
|
hifiGlobalNodeID = id;
|
||||||
|
}
|
||||||
|
|
||||||
if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") {
|
if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") {
|
||||||
jointEyeLeftID = getID(object.properties);
|
jointEyeLeftID = getID(object.properties);
|
||||||
|
|
||||||
|
@ -1354,6 +1408,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
} else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End") {
|
} else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End") {
|
||||||
jointRightToeID = getID(object.properties);
|
jointRightToeID = getID(object.properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
int humanIKJointIndex = humanIKJointNames.indexOf(name);
|
int humanIKJointIndex = humanIKJointNames.indexOf(name);
|
||||||
if (humanIKJointIndex != -1) {
|
if (humanIKJointIndex != -1) {
|
||||||
humanIKJointIDs[humanIKJointIndex] = getID(object.properties);
|
humanIKJointIDs[humanIKJointIndex] = getID(object.properties);
|
||||||
|
@ -1450,6 +1505,25 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
extractBlendshape(subobject) };
|
extractBlendshape(subobject) };
|
||||||
blendshapes.append(blendshape);
|
blendshapes.append(blendshape);
|
||||||
}
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
else if (subobject.name == "TypeFlags") {
|
||||||
|
std::string attributetype = subobject.properties.at(0).toString().toStdString();
|
||||||
|
if (!attributetype.empty()) {
|
||||||
|
if (attributetype == "Light") {
|
||||||
|
std::string lightprop;
|
||||||
|
foreach (const QVariant& vprop, subobject.properties) {
|
||||||
|
lightprop = vprop.toString().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
FBXLight light = extractLight(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::string whatisthat = subobject.name;
|
||||||
|
if (whatisthat == "WTF") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the blendshapes included in the model, if any
|
// add the blendshapes included in the model, if any
|
||||||
|
@ -1624,11 +1698,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
materials.insert(material.id, material);
|
materials.insert(material.id, material);
|
||||||
|
|
||||||
} else if (object.name == "NodeAttribute") {
|
} else if (object.name == "NodeAttribute") {
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
std::vector<std::string> properties;
|
||||||
|
foreach(const QVariant& v, object.properties) {
|
||||||
|
properties.push_back(v.toString().toStdString());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::string attribID = getID(object.properties).toStdString();
|
||||||
|
std::string attributetype;
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
if (subobject.name == "TypeFlags") {
|
if (subobject.name == "TypeFlags") {
|
||||||
typeFlags.insert(getID(object.properties), subobject.properties.at(0).toString());
|
typeFlags.insert(getID(object.properties), subobject.properties.at(0).toString());
|
||||||
|
attributetype = subobject.properties.at(0).toString().toStdString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!attributetype.empty()) {
|
||||||
|
if (attributetype == "Light") {
|
||||||
|
FBXLight light = extractLight(object);
|
||||||
|
lights[attribID] = light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (object.name == "Deformer") {
|
} else if (object.name == "Deformer") {
|
||||||
if (object.properties.last() == "Cluster") {
|
if (object.properties.last() == "Cluster") {
|
||||||
Cluster cluster;
|
Cluster cluster;
|
||||||
|
@ -1666,7 +1757,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
animationCurves.insert(getID(object.properties), curve);
|
animationCurves.insert(getID(object.properties), curve);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
else {
|
||||||
|
std::string objectname = object.name.data();
|
||||||
|
if ( objectname == "Pose"
|
||||||
|
|| objectname == "AnimationStack"
|
||||||
|
|| objectname == "AnimationLayer"
|
||||||
|
|| objectname == "AnimationCurveNode") {
|
||||||
|
} else {
|
||||||
|
unknown++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else if (child.name == "Connections") {
|
} else if (child.name == "Connections") {
|
||||||
foreach (const FBXNode& connection, child.children) {
|
foreach (const FBXNode& connection, child.children) {
|
||||||
|
@ -1675,6 +1779,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
QString childID = getID(connection.properties, 1);
|
QString childID = getID(connection.properties, 1);
|
||||||
QString parentID = getID(connection.properties, 2);
|
QString parentID = getID(connection.properties, 2);
|
||||||
ooChildToParent.insert(childID, parentID);
|
ooChildToParent.insert(childID, parentID);
|
||||||
|
if (!hifiGlobalNodeID.isEmpty() && (parentID == hifiGlobalNodeID)) {
|
||||||
|
std::map< std::string, FBXLight >::iterator lit = lights.find(childID.toStdString());
|
||||||
|
if (lit != lights.end()) {
|
||||||
|
lightmapLevel = (*lit).second.intensity;
|
||||||
|
if (lightmapLevel <= 0.0f) {
|
||||||
|
loadLightmaps = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (connection.properties.at(0) == "OP") {
|
if (connection.properties.at(0) == "OP") {
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
@ -1718,6 +1831,33 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
else {
|
||||||
|
std::string objectname = child.name.data();
|
||||||
|
if ( objectname == "Pose"
|
||||||
|
|| objectname == "CreationTime"
|
||||||
|
|| objectname == "FileId"
|
||||||
|
|| objectname == "Creator"
|
||||||
|
|| objectname == "Documents"
|
||||||
|
|| objectname == "References"
|
||||||
|
|| objectname == "Definitions"
|
||||||
|
|| objectname == "Takes"
|
||||||
|
|| objectname == "AnimationStack"
|
||||||
|
|| objectname == "AnimationLayer"
|
||||||
|
|| objectname == "AnimationCurveNode") {
|
||||||
|
} else {
|
||||||
|
unknown++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check if is code is needed
|
||||||
|
if (!lights.empty()) {
|
||||||
|
if (hifiGlobalNodeID.isEmpty()) {
|
||||||
|
std::map< std::string, FBXLight >::iterator l = lights.begin();
|
||||||
|
lightmapLevel = (*l).second.intensity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign the blendshapes to their corresponding meshes
|
// assign the blendshapes to their corresponding meshes
|
||||||
|
@ -1956,7 +2096,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
emissiveParams.y = lightmapLevel;
|
emissiveParams.y = lightmapLevel;
|
||||||
QString emissiveTextureID = emissiveTextures.value(childID);
|
QString emissiveTextureID = emissiveTextures.value(childID);
|
||||||
QString ambientTextureID = ambientTextures.value(childID);
|
QString ambientTextureID = ambientTextures.value(childID);
|
||||||
if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) {
|
if (loadLightmaps && (!emissiveTextureID.isNull() || !ambientTextureID.isNull())) {
|
||||||
|
|
||||||
if (!emissiveTextureID.isNull()) {
|
if (!emissiveTextureID.isNull()) {
|
||||||
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
|
|
|
@ -165,6 +165,22 @@ public:
|
||||||
QVector<glm::quat> rotations;
|
QVector<glm::quat> rotations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A light in an FBX document.
|
||||||
|
class FBXLight {
|
||||||
|
public:
|
||||||
|
QString name;
|
||||||
|
Transform transform;
|
||||||
|
float intensity;
|
||||||
|
glm::vec3 color;
|
||||||
|
|
||||||
|
FBXLight() :
|
||||||
|
name(),
|
||||||
|
transform(),
|
||||||
|
intensity(1.0f),
|
||||||
|
color(1.0f)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FBXAnimationFrame)
|
Q_DECLARE_METATYPE(FBXAnimationFrame)
|
||||||
Q_DECLARE_METATYPE(QVector<FBXAnimationFrame>)
|
Q_DECLARE_METATYPE(QVector<FBXAnimationFrame>)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue