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:
Philip Rosedale 2014-12-05 10:07:52 -08:00
commit 0ad361fd60
3 changed files with 195 additions and 23 deletions

View file

@ -829,28 +829,44 @@ void GeometryReader::run() {
return;
}
try {
std::string urlname = _url.path().toLower().toStdString();
FBXGeometry fbxgeo;
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);
if (!_reply) {
throw QString("Reply is NULL ?!");
}
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) {
qDebug() << "Error reading " << _url << ": " << error;
QMetaObject::invokeMethod(geometry.data(), "finishedLoading", Q_ARG(bool, false));

View file

@ -1046,6 +1046,7 @@ FBXBlendshape extractBlendshape(const FBXNode& object) {
return blendshape;
}
void setTangents(FBXMesh& mesh, int firstIndex, int secondIndex) {
const glm::vec3& normal = mesh.normals.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) {
QHash<QString, ExtractedMesh> meshes;
QHash<QString, QString> modelIDsToNames;
@ -1222,6 +1261,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
QHash<QString, QString> yComponents;
QHash<QString, QString> zComponents;
std::map<std::string, FBXLight> lights;
QVariantHash joints = mapping.value("joint").toHash();
QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft")));
QString jointEyeRightName = processID(getString(joints.value("jointEyeRight", "jointEyeRight")));
@ -1276,6 +1317,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
#endif
FBXGeometry geometry;
float unitScaleFactor = 1.0f;
glm::vec3 ambientColor;
QString hifiGlobalNodeID;
foreach (const FBXNode& child, node.children) {
if (child.name == "FBXHeaderExtension") {
@ -1302,10 +1345,16 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
} else if (child.name == "GlobalSettings") {
foreach (const FBXNode& object, child.children) {
if (object.name == "Properties70") {
QString propertyName = "P";
int index = 4;
foreach (const FBXNode& subobject, object.children) {
if (subobject.name == "P" && subobject.properties.size() >= 5 &&
subobject.properties.at(0) == "UnitScaleFactor") {
unitScaleFactor = subobject.properties.at(4).toFloat();
if (subobject.name == propertyName) {
std::string subpropName = subobject.properties.at(0).toString().toStdString();
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);
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") {
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") {
jointRightToeID = getID(object.properties);
}
int humanIKJointIndex = humanIKJointNames.indexOf(name);
if (humanIKJointIndex != -1) {
humanIKJointIDs[humanIKJointIndex] = getID(object.properties);
@ -1450,6 +1505,25 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
extractBlendshape(subobject) };
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
@ -1624,11 +1698,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
materials.insert(material.id, material);
} 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) {
if (subobject.name == "TypeFlags") {
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") {
if (object.properties.last() == "Cluster") {
Cluster cluster;
@ -1666,7 +1757,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
}
}
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") {
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 parentID = getID(connection.properties, 2);
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") {
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
@ -1956,7 +2096,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
emissiveParams.y = lightmapLevel;
QString emissiveTextureID = emissiveTextures.value(childID);
QString ambientTextureID = ambientTextures.value(childID);
if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) {
if (loadLightmaps && (!emissiveTextureID.isNull() || !ambientTextureID.isNull())) {
if (!emissiveTextureID.isNull()) {
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);

View file

@ -165,6 +165,22 @@ public:
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(QVector<FBXAnimationFrame>)