mirror of
https://github.com/overte-org/overte.git
synced 2025-07-25 22:39:53 +02:00
Fix baked models not preserving scale in some cases
This commit is contained in:
parent
d8ba08ec2d
commit
94e51b136c
8 changed files with 131 additions and 4 deletions
|
@ -142,6 +142,27 @@ void FBXBaker::rewriteAndBakeSceneModels(const QVector<hfm::Mesh>& meshes, const
|
||||||
} else if (object->name == "Texture" || object->name == "Video") {
|
} else if (object->name == "Texture" || object->name == "Video") {
|
||||||
// this is an embedded texture, we need to remove it from the FBX
|
// this is an embedded texture, we need to remove it from the FBX
|
||||||
object = rootChild.children.erase(object);
|
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 {
|
} else {
|
||||||
object++;
|
object++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,8 +59,8 @@ namespace scriptable {
|
||||||
* @property {string} occlusionMap
|
* @property {string} occlusionMap
|
||||||
* @property {string} lightmapMap
|
* @property {string} lightmapMap
|
||||||
* @property {string} scatteringMap
|
* @property {string} scatteringMap
|
||||||
* @property {string} texCoordTransform0
|
* @property {Mat4|string} texCoordTransform0
|
||||||
* @property {string} texCoordTransform1
|
* @property {Mat4|string} texCoordTransform1
|
||||||
* @property {string} lightmapParams
|
* @property {string} lightmapParams
|
||||||
* @property {string} materialParams
|
* @property {string} materialParams
|
||||||
* @property {boolean} defaultFallthrough
|
* @property {boolean} defaultFallthrough
|
||||||
|
@ -93,6 +93,7 @@ namespace scriptable {
|
||||||
QString occlusionMap;
|
QString occlusionMap;
|
||||||
QString lightmapMap;
|
QString lightmapMap;
|
||||||
QString scatteringMap;
|
QString scatteringMap;
|
||||||
|
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texCoordTransforms;
|
||||||
|
|
||||||
bool defaultFallthrough;
|
bool defaultFallthrough;
|
||||||
std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script
|
std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script
|
||||||
|
|
|
@ -470,9 +470,13 @@ namespace scriptable {
|
||||||
// These need to be implemented, but set the fallthrough for now
|
// These need to be implemented, but set the fallthrough for now
|
||||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) {
|
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) {
|
||||||
obj.setProperty("texCoordTransform0", FALLTHROUGH);
|
obj.setProperty("texCoordTransform0", FALLTHROUGH);
|
||||||
|
} else {
|
||||||
|
obj.setProperty("texCoordTransform0", mat4toScriptValue(engine, material.texCoordTransforms[0]));
|
||||||
}
|
}
|
||||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) {
|
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) {
|
||||||
obj.setProperty("texCoordTransform1", FALLTHROUGH);
|
obj.setProperty("texCoordTransform1", FALLTHROUGH);
|
||||||
|
} else {
|
||||||
|
obj.setProperty("texCoordTransform1", mat4toScriptValue(engine, material.texCoordTransforms[1]));
|
||||||
}
|
}
|
||||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) {
|
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) {
|
||||||
obj.setProperty("lightmapParams", FALLTHROUGH);
|
obj.setProperty("lightmapParams", FALLTHROUGH);
|
||||||
|
|
|
@ -119,6 +119,10 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint
|
||||||
if (map && map->getTextureSource()) {
|
if (map && map->getTextureSource()) {
|
||||||
scatteringMap = map->getTextureSource()->getUrl().toString();
|
scatteringMap = map->getTextureSource()->getUrl().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) {
|
||||||
|
texCoordTransforms[i] = material->getTexCoordTransform(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -324,6 +324,7 @@ public:
|
||||||
void setModel(const std::string& model) { _model = model; }
|
void setModel(const std::string& model) { _model = model; }
|
||||||
|
|
||||||
glm::mat4 getTexCoordTransform(uint i) const { return _texcoordTransforms[i]; }
|
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 getLightmapParams() const { return _lightmapParams; }
|
||||||
glm::vec2 getMaterialParams() const { return _materialParams; }
|
glm::vec2 getMaterialParams() const { return _materialParams; }
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,9 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
||||||
material->setModel(modelString);
|
material->setModel(modelString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<bool, graphics::Material::NUM_TEXCOORD_TRANSFORMS> hasTexcoordTransform;
|
||||||
|
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texcoordTransforms;
|
||||||
|
|
||||||
if (modelString == HIFI_PBR) {
|
if (modelString == HIFI_PBR) {
|
||||||
const QString FALLTHROUGH("fallthrough");
|
const QString FALLTHROUGH("fallthrough");
|
||||||
for (auto& key : materialJSON.keys()) {
|
for (auto& key : materialJSON.keys()) {
|
||||||
|
@ -372,8 +375,12 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
||||||
if (valueString == FALLTHROUGH) {
|
if (valueString == FALLTHROUGH) {
|
||||||
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::TEXCOORDTRANSFORM0);
|
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") {
|
} else if (key == "texCoordTransform1") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
|
@ -381,8 +388,12 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
||||||
if (valueString == FALLTHROUGH) {
|
if (valueString == FALLTHROUGH) {
|
||||||
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::TEXCOORDTRANSFORM1);
|
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") {
|
} else if (key == "lightmapParams") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
|
@ -409,6 +420,14 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> 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<std::string, std::shared_ptr<NetworkMaterial>>(name, material);
|
return std::pair<std::string, std::shared_ptr<NetworkMaterial>>(name, material);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -636,6 +636,79 @@ void mat4FromScriptValue(const QScriptValue& object, glm::mat4& mat4) {
|
||||||
mat4[3][3] = object.property("r3c3").toVariant().toFloat();
|
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<float>()) {
|
||||||
|
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<glm::vec3>& vector) {
|
QScriptValue qVectorVec3ColorToScriptValue(QScriptEngine* engine, const QVector<glm::vec3>& vector) {
|
||||||
QScriptValue array = engine->newArray();
|
QScriptValue array = engine->newArray();
|
||||||
for (int i = 0; i < vector.size(); i++) {
|
for (int i = 0; i < vector.size(); i++) {
|
||||||
|
|
|
@ -67,6 +67,10 @@ void registerMetaTypes(QScriptEngine* engine);
|
||||||
QScriptValue mat4toScriptValue(QScriptEngine* engine, const glm::mat4& mat4);
|
QScriptValue mat4toScriptValue(QScriptEngine* engine, const glm::mat4& mat4);
|
||||||
void mat4FromScriptValue(const QScriptValue& object, 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
|
/**jsdoc
|
||||||
* A 2-dimensional vector.
|
* A 2-dimensional vector.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue