From 55b677dd02b40150869d782d8387b57d807ed295 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 7 May 2014 12:53:38 -0700 Subject: [PATCH 1/2] Provide options for model translation: by default, pivot about mesh bounds' center; allow numeric translation or pivot about joint position. --- interface/src/ModelUploader.cpp | 52 +++++++++++++++++++++++++++++++-- interface/src/ModelUploader.h | 7 +++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 08719f0f25..ce8691998d 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include #include @@ -42,6 +43,9 @@ static const QString TEXDIR_FIELD = "texdir"; static const QString LOD_FIELD = "lod"; static const QString JOINT_INDEX_FIELD = "jointIndex"; static const QString SCALE_FIELD = "scale"; +static const QString TRANSLATION_X_FIELD = "tx"; +static const QString TRANSLATION_Y_FIELD = "ty"; +static const QString TRANSLATION_Z_FIELD = "tz"; static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; @@ -519,6 +523,14 @@ bool ModelUploader::addPart(const QFile& file, const QByteArray& contents, const return true; } +static QDoubleSpinBox* createTranslationBox() { + QDoubleSpinBox* box = new QDoubleSpinBox(); + const double MAX_TRANSLATION = 1000000.0; + box->setMinimum(-MAX_TRANSLATION); + box->setMaximum(MAX_TRANSLATION); + return box; +} + ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariantHash& originalMapping, const QString& basePath, const FBXGeometry& geometry) : _modelType(modelType), @@ -540,7 +552,18 @@ ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariant _scale->setMaximum(FLT_MAX); _scale->setSingleStep(0.01); - if (_modelType != ATTACHMENT_MODEL) { + if (_modelType == ATTACHMENT_MODEL) { + QHBoxLayout* translation = new QHBoxLayout(); + form->addRow("Translation:", translation); + translation->addWidget(_translationX = createTranslationBox()); + translation->addWidget(_translationY = createTranslationBox()); + translation->addWidget(_translationZ = createTranslationBox()); + form->addRow("Pivot About Center:", _pivotAboutCenter = new QCheckBox()); + form->addRow("Pivot Joint:", _pivotJoint = createJointBox()); + connect(_pivotAboutCenter, SIGNAL(toggled(bool)), SLOT(updatePivotJoint())); + _pivotAboutCenter->setChecked(true); + + } else { form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox()); form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox()); form->addRow("Neck Joint:", _neckJoint = createJointBox()); @@ -584,7 +607,19 @@ QVariantHash ModelPropertiesDialog::getMapping() const { mapping.insert(JOINT_INDEX_FIELD, jointIndices); QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); - if (_modelType != ATTACHMENT_MODEL) { + if (_modelType == ATTACHMENT_MODEL) { + glm::vec3 pivot; + if (_pivotAboutCenter->isChecked()) { + pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f; + + } else if (_pivotJoint->currentIndex() != 0) { + pivot = extractTranslation(_geometry.joints.at(_pivotJoint->currentIndex() - 1).transform); + } + mapping.insert(TRANSLATION_X_FIELD, -pivot.x * _scale->value() + _translationX->value()); + mapping.insert(TRANSLATION_Y_FIELD, -pivot.y * _scale->value() + _translationY->value()); + mapping.insert(TRANSLATION_Z_FIELD, -pivot.z * _scale->value() + _translationZ->value()); + + } else { insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText()); insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText()); insertJointMapping(joints, "jointNeck", _neckJoint->currentText()); @@ -617,7 +652,14 @@ void ModelPropertiesDialog::reset() { _scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble()); QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash(); - if (_modelType != ATTACHMENT_MODEL) { + if (_modelType == ATTACHMENT_MODEL) { + _translationX->setValue(_originalMapping.value(TRANSLATION_X_FIELD).toDouble()); + _translationY->setValue(_originalMapping.value(TRANSLATION_Y_FIELD).toDouble()); + _translationZ->setValue(_originalMapping.value(TRANSLATION_Z_FIELD).toDouble()); + _pivotAboutCenter->setChecked(true); + _pivotJoint->setCurrentIndex(0); + + } else { setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString()); setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString()); setJointText(_neckJoint, jointHash.value("jointNeck").toString()); @@ -654,6 +696,10 @@ void ModelPropertiesDialog::chooseTextureDirectory() { _textureDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1)); } +void ModelPropertiesDialog::updatePivotJoint() { + _pivotJoint->setEnabled(!_pivotAboutCenter->isChecked()); +} + void ModelPropertiesDialog::createNewFreeJoint(const QString& joint) { QWidget* freeJoint = new QWidget(); QHBoxLayout* freeJointLayout = new QHBoxLayout(); diff --git a/interface/src/ModelUploader.h b/interface/src/ModelUploader.h index 499bfad03b..766bd55318 100644 --- a/interface/src/ModelUploader.h +++ b/interface/src/ModelUploader.h @@ -19,6 +19,7 @@ #include "ui/ModelsBrowser.h" +class QCheckBox; class QComboBox; class QDoubleSpinBox; class QFileInfo; @@ -83,6 +84,7 @@ public: private slots: void reset(); void chooseTextureDirectory(); + void updatePivotJoint(); void createNewFreeJoint(const QString& joint = QString()); private: @@ -96,6 +98,11 @@ private: QLineEdit* _name; QPushButton* _textureDirectory; QDoubleSpinBox* _scale; + QDoubleSpinBox* _translationX; + QDoubleSpinBox* _translationY; + QDoubleSpinBox* _translationZ; + QCheckBox* _pivotAboutCenter; + QComboBox* _pivotJoint; QComboBox* _leftEyeJoint; QComboBox* _rightEyeJoint; QComboBox* _neckJoint; From 03faff359f1772cd587ea37360981409c46fa968 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 7 May 2014 14:48:25 -0700 Subject: [PATCH 2/2] Fix for certain models with textures not parented to materials. --- libraries/fbx/src/FBXReader.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index d637526067..1fc03ceb66 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -826,7 +826,7 @@ ExtractedMesh extractMesh(const FBXNode& object) { while (endIndex < data.polygonIndices.size() && data.polygonIndices.at(endIndex++) >= 0); QPair materialTexture((polygonIndex < materials.size()) ? materials.at(polygonIndex) : 0, - (polygonIndex < textures.size()) ? textures.at(polygonIndex) : -1); + (polygonIndex < textures.size()) ? textures.at(polygonIndex) : 0); int& partIndex = materialTextureParts[materialTexture]; if (partIndex == 0) { data.extracted.partMaterialTextures.append(materialTexture); @@ -972,6 +972,18 @@ FBXTexture getTexture(const QString& textureID, const QHash return texture; } +bool checkMaterialsHaveTextures(const QHash& materials, + const QHash& textureFilenames, const QMultiHash& childMap) { + foreach (const QString& materialID, materials.keys()) { + foreach (const QString& childID, childMap.values(materialID)) { + if (textureFilenames.contains(childID)) { + return true; + } + } + } + return false; +} + FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { QHash meshes; QVector blendshapes; @@ -1515,6 +1527,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) geometry.bindExtents.reset(); geometry.meshExtents.reset(); + // see if any materials have texture children + bool materialsHaveTextures = checkMaterialsHaveTextures(materials, textureFilenames, childMap); + for (QHash::iterator it = meshes.begin(); it != meshes.end(); it++) { ExtractedMesh& extracted = it.value(); @@ -1587,7 +1602,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (textureFilenames.contains(childID)) { FBXTexture texture = getTexture(childID, textureFilenames, textureContent); for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { - if (extracted.partMaterialTextures.at(j).second == textureIndex) { + int partTexture = extracted.partMaterialTextures.at(j).second; + if (partTexture == textureIndex && !(partTexture == 0 && materialsHaveTextures)) { extracted.mesh.parts[j].diffuseTexture = texture; } }