diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index 01897ee5e9..9b80041bcf 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -142,6 +142,27 @@ void FBXBaker::rewriteAndBakeSceneModels(const QVector& meshes, const } else if (object->name == "Texture" || object->name == "Video") { // this is an embedded texture, we need to remove it from the FBX object = rootChild.children.erase(object); + } else if (object->name == "Material") { + for (FBXNode& materialChild : object->children) { + if (materialChild.name == "Properties60" || materialChild.name == "Properties70") { + // This is a properties node + // Remove the material texture scale because that is now included in the material JSON + // Texture nodes are removed, so their texture scale is effectively gone already + static const QVariant MAYA_UV_SCALE = hifi::ByteArray("Maya|uv_scale"); + static const QVariant MAYA_UV_OFFSET = hifi::ByteArray("Maya|uv_offset"); + for (int i = 0; i < materialChild.children.size(); i++) { + const auto& prop = materialChild.children[i]; + const auto& propertyName = prop.properties.at(0); + if (propertyName == MAYA_UV_SCALE || + propertyName == MAYA_UV_OFFSET) { + materialChild.children.removeAt(i); + --i; + } + } + } + } + + object++; } else { object++; } diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index d2d330167d..6d1b9d83d2 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -59,8 +59,8 @@ namespace scriptable { * @property {string} occlusionMap * @property {string} lightmapMap * @property {string} scatteringMap - * @property {string} texCoordTransform0 - * @property {string} texCoordTransform1 + * @property {Mat4|string} texCoordTransform0 + * @property {Mat4|string} texCoordTransform1 * @property {string} lightmapParams * @property {string} materialParams * @property {boolean} defaultFallthrough @@ -93,6 +93,7 @@ namespace scriptable { QString occlusionMap; QString lightmapMap; QString scatteringMap; + std::array texCoordTransforms; bool defaultFallthrough; std::unordered_map propertyFallthroughs; // not actually exposed to script diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index 3bd4af601c..4182b52309 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -470,9 +470,13 @@ namespace scriptable { // These need to be implemented, but set the fallthrough for now if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) { obj.setProperty("texCoordTransform0", FALLTHROUGH); + } else { + obj.setProperty("texCoordTransform0", mat4toScriptValue(engine, material.texCoordTransforms[0])); } if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) { obj.setProperty("texCoordTransform1", FALLTHROUGH); + } else { + obj.setProperty("texCoordTransform1", mat4toScriptValue(engine, material.texCoordTransforms[1])); } if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) { obj.setProperty("lightmapParams", FALLTHROUGH); diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp index caee4ceb2a..8825a26bfe 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp @@ -119,6 +119,10 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint if (map && map->getTextureSource()) { scatteringMap = map->getTextureSource()->getUrl().toString(); } + + for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { + texCoordTransforms[i] = material->getTexCoordTransform(i); + } } } diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 80b247bed0..330feaa61c 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -324,6 +324,7 @@ public: void setModel(const std::string& model) { _model = model; } glm::mat4 getTexCoordTransform(uint i) const { return _texcoordTransforms[i]; } + void setTexCoordTransform(uint i, const glm::mat4& mat4) { _texcoordTransforms[i] = mat4; } glm::vec2 getLightmapParams() const { return _lightmapParams; } glm::vec2 getMaterialParams() const { return _materialParams; } diff --git a/libraries/material-networking/src/material-networking/MaterialCache.cpp b/libraries/material-networking/src/material-networking/MaterialCache.cpp index 5a5f4ab54b..9d6fc06d01 100644 --- a/libraries/material-networking/src/material-networking/MaterialCache.cpp +++ b/libraries/material-networking/src/material-networking/MaterialCache.cpp @@ -177,6 +177,9 @@ std::pair> NetworkMaterialResource material->setModel(modelString); } + std::array hasTexcoordTransform; + std::array texcoordTransforms; + if (modelString == HIFI_PBR) { const QString FALLTHROUGH("fallthrough"); for (auto& key : materialJSON.keys()) { @@ -372,8 +375,12 @@ std::pair> NetworkMaterialResource if (valueString == FALLTHROUGH) { material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::TEXCOORDTRANSFORM0); } + } else if (value.isObject()) { + auto valueVariant = value.toVariant(); + glm::mat4 transform = mat4FromVariant(valueVariant); + hasTexcoordTransform[0] = true; + texcoordTransforms[0] = transform; } - // TODO: implement texCoordTransform0 } else if (key == "texCoordTransform1") { auto value = materialJSON.value(key); if (value.isString()) { @@ -381,8 +388,12 @@ std::pair> NetworkMaterialResource if (valueString == FALLTHROUGH) { material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::TEXCOORDTRANSFORM1); } + } else if (value.isObject()) { + auto valueVariant = value.toVariant(); + glm::mat4 transform = mat4FromVariant(valueVariant); + hasTexcoordTransform[1] = true; + texcoordTransforms[1] = transform; } - // TODO: implement texCoordTransform1 } else if (key == "lightmapParams") { auto value = materialJSON.value(key); if (value.isString()) { @@ -409,6 +420,14 @@ std::pair> NetworkMaterialResource } } } + + // Do this after the texture maps are defined, so it overrides the default transforms + for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { + if (hasTexcoordTransform[i]) { + material->setTexCoordTransform(i, texcoordTransforms[i]); + } + } + return std::pair>(name, material); } diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 597e537d8d..e453b7bff4 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -636,6 +636,79 @@ void mat4FromScriptValue(const QScriptValue& object, glm::mat4& mat4) { mat4[3][3] = object.property("r3c3").toVariant().toFloat(); } +QVariant mat4ToVariant(const glm::mat4& mat4) { + if (mat4 != mat4) { + // NaN + return QVariant(); + } + QVariantMap object; + + object["r0c0"] = mat4[0][0]; + object["r1c0"] = mat4[0][1]; + object["r2c0"] = mat4[0][2]; + object["r3c0"] = mat4[0][3]; + object["r0c1"] = mat4[1][0]; + object["r1c1"] = mat4[1][1]; + object["r2c1"] = mat4[1][2]; + object["r3c1"] = mat4[1][3]; + object["r0c2"] = mat4[2][0]; + object["r1c2"] = mat4[2][1]; + object["r2c2"] = mat4[2][2]; + object["r3c2"] = mat4[2][3]; + object["r0c3"] = mat4[3][0]; + object["r1c3"] = mat4[3][1]; + object["r2c3"] = mat4[3][2]; + object["r3c3"] = mat4[3][3]; + + return object; +} + +glm::mat4 mat4FromVariant(const QVariant& object, bool& valid) { + glm::mat4 mat4; + valid = false; + if (!object.isValid() || object.isNull()) { + return mat4; + } else { + const static auto getElement = [](const QVariantMap& map, const char * key, float& value, bool& everyConversionValid) { + auto variantValue = map[key]; + if (variantValue.canConvert()) { + value = variantValue.toFloat(); + } else { + everyConversionValid = false; + } + }; + + auto map = object.toMap(); + bool everyConversionValid = true; + + getElement(map, "r0c0", mat4[0][0], everyConversionValid); + getElement(map, "r1c0", mat4[0][1], everyConversionValid); + getElement(map, "r2c0", mat4[0][2], everyConversionValid); + getElement(map, "r3c0", mat4[0][3], everyConversionValid); + getElement(map, "r0c1", mat4[1][0], everyConversionValid); + getElement(map, "r1c1", mat4[1][1], everyConversionValid); + getElement(map, "r2c1", mat4[1][2], everyConversionValid); + getElement(map, "r3c1", mat4[1][3], everyConversionValid); + getElement(map, "r0c2", mat4[2][0], everyConversionValid); + getElement(map, "r1c2", mat4[2][1], everyConversionValid); + getElement(map, "r2c2", mat4[2][2], everyConversionValid); + getElement(map, "r3c2", mat4[2][3], everyConversionValid); + getElement(map, "r0c3", mat4[3][0], everyConversionValid); + getElement(map, "r1c3", mat4[3][1], everyConversionValid); + getElement(map, "r2c3", mat4[3][2], everyConversionValid); + getElement(map, "r3c3", mat4[3][3], everyConversionValid); + + if (everyConversionValid) { + valid = true; + } + } +} + +glm::mat4 mat4FromVariant(const QVariant& object) { + bool valid = false; + return mat4FromVariant(object, valid); +} + QScriptValue qVectorVec3ColorToScriptValue(QScriptEngine* engine, const QVector& vector) { QScriptValue array = engine->newArray(); for (int i = 0; i < vector.size(); i++) { diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index ea2c5b8354..96c64f7384 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -67,6 +67,10 @@ void registerMetaTypes(QScriptEngine* engine); QScriptValue mat4toScriptValue(QScriptEngine* engine, const glm::mat4& mat4); void mat4FromScriptValue(const QScriptValue& object, glm::mat4& mat4); +QVariant mat4ToVariant(const glm::mat4& mat4); +glm::mat4 mat4FromVariant(const QVariant& object, bool& valid); +glm::mat4 mat4FromVariant(const QVariant& object); + /**jsdoc * A 2-dimensional vector. *