示例#1
0
void ModelBaker::outputUnbakedFST() {
    // Output an unbaked FST file in the original output folder to make it easier for FSTBaker to rebake this model
    // TODO: Consider a more robust method that does not depend on FSTBaker navigating to a hardcoded relative path
    QString outputFSTFilename = _modelURL.fileName();
    auto extensionStart = outputFSTFilename.indexOf(".");
    if (extensionStart != -1) {
        outputFSTFilename.resize(extensionStart);
    }
    outputFSTFilename += FST_EXTENSION;
    QString outputFSTURL = _originalOutputDir + "/" + outputFSTFilename;

    hifi::VariantHash outputMapping;
    outputMapping[FST_VERSION_FIELD] = FST_VERSION;
    outputMapping[FILENAME_FIELD] = _modelURL.fileName();
    outputMapping[COMMENT_FIELD] = "This FST file was generated by Oven for use during rebaking. It is not part of the original model. This file's existence is subject to change.";
    hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping);

    QFile fstOutputFile { outputFSTURL };
    if (fstOutputFile.exists()) {
        handleWarning("The file '" + outputFSTURL + "' already exists. Should that be baked instead of '" + _modelURL.toString() + "'?");
        return;
    }
    if (!fstOutputFile.open(QIODevice::WriteOnly)) {
        handleWarning("Failed to open file '" + outputFSTURL + "' for writing. Rebaking may fail on the associated model.");
        return;
    }
    if (fstOutputFile.write(fstOut) == -1) {
        handleWarning("Failed to write to file '" + outputFSTURL + "'. Rebaking may fail on the associated model.");
    }
}
示例#2
0
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setupSceneStateTransitions();

    connect(&scene, SIGNAL(error(QString)), this, SLOT(handleError(QString)));
    connect(&scene, SIGNAL(warning(QString)), this, SLOT(handleWarning(QString)));
    connect(&scene, SIGNAL(notice(QString)), this, SLOT(handleNotice(QString)));

    connect(&score, SIGNAL(error(QString)), this, SLOT(handleError(QString)));
    connect(&score, SIGNAL(warning(QString)), this, SLOT(handleWarning(QString)));
    connect(&score, SIGNAL(notice(QString)), this, SLOT(handleNotice(QString)));

    connect(&scene, SIGNAL(userAction(UserAction)), &score, SLOT(userAction(UserAction)));
    connect(&score, SIGNAL(changed(ScoreChange)), &scene, SLOT(scoreChange(ScoreChange)));

    connect((ui->VoiceList), SIGNAL(userAction(UserAction)), &score, SLOT(userAction(UserAction)));
    connect(&score, SIGNAL(changed(ScoreChange)), (ui->VoiceList), SLOT(scoreChange(ScoreChange)));

    connect(ui->properSpinBox, SIGNAL(userAction(UserAction)), &score, SLOT(userAction(UserAction)));
    connect(&score, SIGNAL(changed(ScoreChange)), ui->properSpinBox, SLOT(scoreChanged(ScoreChange)));

    connect((ui->VoiceList), SIGNAL(voiceCheckedSignal(IdType,bool)), &scene, SLOT(voiceVisible(IdType,bool)));
    connect((ui->VoiceList), SIGNAL(voiceSelectedSignal(IdType)), &scene, SLOT(selectVoice(IdType)));

    ui->systemView->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    ui->systemView->setScene(&scene);
}
示例#3
0
void ModelBaker::handleFinishedMaterialBaker() {
    auto baker = qobject_cast<MaterialBaker*>(sender());

    if (baker) {
        if (!baker->hasErrors()) {
            // this MaterialBaker is done and everything went according to plan
            qCDebug(model_baking) << "Adding baked material to FST mapping " << baker->getBakedMaterialData();

            QString relativeBakedMaterialURL = _modelURL.fileName();
            auto baseName = relativeBakedMaterialURL.left(relativeBakedMaterialURL.lastIndexOf('.'));
            relativeBakedMaterialURL = baseName + BAKED_MATERIAL_EXTENSION;

            auto materialResource = baker->getNetworkMaterialResource();
            if (materialResource) {
                for (auto materialName : materialResource->parsedMaterials.names) {
                    QJsonObject json;
                    json[QString("mat::" + QString(materialName.c_str()))] = relativeBakedMaterialURL + "#" + materialName.c_str();
                    _materialMappingJSON.push_back(json);
                }
            }
        } else {
            // this material failed to bake - this doesn't fail the entire bake but we need to add the errors from
            // the material to our warnings
            _warningList << baker->getWarnings();
        }
    } else {
        handleWarning("Failed to bake the materials for model with URL " + _modelURL.toString());
    }

    bakeMaterialMap();
}
bool TestCaseSandboxResultDecoderImpl::decode()
{
    switch(channel->readByte())
    {
    case startCmd:
        handleStartCase();
        break;
    case endCmd:
        handleEndCase();
        return true;
    case errorCmd:
        handleError();
        break;
    case failureCmd:
        handleAssertionFailure();
        break;
    case infoCmd:
        handleInfo();
        break;
    case warningCmd:
        handleWarning();
        break;
    default:
        handleInternalError();
    }
    return false;
}
示例#5
0
QString ModelBaker::compressTexture(QString modelTextureFileName, image::TextureUsage::Type textureType) {

    QFileInfo modelTextureFileInfo{ modelTextureFileName.replace("\\", "/") };
    
    if (modelTextureFileInfo.suffix() == BAKED_TEXTURE_EXT.mid(1)) {
        // re-baking a model that already references baked textures
        // this is an error - return from here
        handleError("Cannot re-bake a file that already references compressed textures");
        return QString::null;
    }

    if (!image::getSupportedFormats().contains(modelTextureFileInfo.suffix())) {
        // this is a texture format we don't bake, skip it
        handleWarning(modelTextureFileName + " is not a bakeable texture format");
        return QString::null;
    }

    // make sure this texture points to something and isn't one we've already re-mapped
    QString textureChild { QString::null };
    if (!modelTextureFileInfo.filePath().isEmpty()) {
        // check if this was an embedded texture that we already have in-memory content for
        QByteArray textureContent;
        
        // figure out the URL to this texture, embedded or external
        if (!modelTextureFileInfo.filePath().isEmpty()) {
            textureContent = _textureContentMap.value(modelTextureFileName.toLocal8Bit());
        }
        auto urlToTexture = getTextureURL(modelTextureFileInfo, modelTextureFileName, !textureContent.isNull());

        QString bakedTextureFileName;
        if (_remappedTexturePaths.contains(urlToTexture)) {
            bakedTextureFileName = _remappedTexturePaths[urlToTexture];
        } else {
            // construct the new baked texture file name and file path
            // ensuring that the baked texture will have a unique name
            // even if there was another texture with the same name at a different path
            bakedTextureFileName = createBakedTextureFileName(modelTextureFileInfo);
            _remappedTexturePaths[urlToTexture] = bakedTextureFileName;
        }

        qCDebug(model_baking).noquote() << "Re-mapping" << modelTextureFileName
            << "to" << bakedTextureFileName;

        QString bakedTextureFilePath{
            _bakedOutputDir + "/" + bakedTextureFileName
        };

        textureChild = bakedTextureFileName;

        if (!_bakingTextures.contains(urlToTexture)) {
            _outputFiles.push_back(bakedTextureFilePath);

            // bake this texture asynchronously
            bakeTexture(urlToTexture, textureType, _bakedOutputDir, bakedTextureFileName, textureContent);
        }
    }
   
    return textureChild;
}
示例#6
0
SelectWnd::SelectWnd(LXQt::Settings* settings, QWidget *parent) : QWidget(parent), mSettings(settings)
{
    setupUi(this);

    warningLabel->hide();

    mModel = new XCursorThemeModel(this);

    int size = style()->pixelMetric(QStyle::PM_LargeIconSize);
    lbThemes->setModel(mModel);
    lbThemes->setItemDelegate(new ItemDelegate(this));
    lbThemes->setIconSize(QSize(size, size));
    lbThemes->setSelectionMode(QAbstractItemView::SingleSelection);

    // Make sure we find out about selection changes
    connect(lbThemes->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
            SLOT(currentChanged(const QModelIndex &, const QModelIndex &)));
    // display/hide warning label
    connect(mModel, SIGNAL(modelReset()),
                    this, SLOT(handleWarning()));
    connect(mModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
                    this, SLOT(handleWarning()));
    connect(mModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
                    this, SLOT(handleWarning()));

    connect(warningLabel, SIGNAL(showDirInfo()),
                    this, SLOT(showDirInfo()));

    // Disable the install button if we can't install new themes to ~/.icons,
    // or Xcursor isn't set up to look for cursor themes there
    btInstall->setEnabled(mModel->searchPaths().contains(HOME_ICON_DIR) && iconsIsWritable());
    // TODO/FIXME: btInstall functionality
    btInstall->hide();
    btRemove->hide();

    //QTimer::singleShot(0, this, SLOT(setCurrent()));

    handleWarning();
}
示例#7
0
void ModelBaker::handleFinishedMaterialMapBaker() {
    auto baker = qobject_cast<MaterialBaker*>(sender());

    if (baker) {
        if (!baker->hasErrors()) {
            // this MaterialBaker is done and everything went according to plan
            qCDebug(model_baking) << "Adding baked material to FST mapping " << baker->getBakedMaterialData();

            QString materialName;
            {
                auto materialResource = baker->getNetworkMaterialResource();
                if (materialResource) {
                    auto url = materialResource->getURL();
                    if (!url.isEmpty()) {
                        QString urlString = url.toDisplayString();
                        auto index = urlString.lastIndexOf("#");
                        if (index != -1) {
                            materialName = urlString.right(urlString.length() - index);
                        }
                    }
                }
            }

            QJsonObject json;
            json[QString(_materialMapping.front().first.c_str())] = baker->getMaterialData() + BAKED_MATERIAL_EXTENSION + materialName;
            _materialMappingJSON.push_back(json);
        } else {
            // this material failed to bake - this doesn't fail the entire bake but we need to add the errors from
            // the material to our warnings
            _warningList << baker->getWarnings();
        }
    } else {
        handleWarning("Failed to bake the materialMap for model with URL " + _modelURL.toString() + " and mapping target " + _materialMapping.front().first.c_str());
    }

    _materialMapping.erase(_materialMapping.begin());
    bakeMaterialMap();
}
示例#8
0
bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback) {
    if (mesh.wasCompressed) {
        handleError("Cannot re-bake a file that contains compressed mesh");
        return false;
    }

    Q_ASSERT(mesh.normals.size() == 0 || mesh.normals.size() == mesh.vertices.size());
    Q_ASSERT(mesh.colors.size() == 0 || mesh.colors.size() == mesh.vertices.size());
    Q_ASSERT(mesh.texCoords.size() == 0 || mesh.texCoords.size() == mesh.vertices.size());

    int64_t numTriangles{ 0 };
    for (auto& part : mesh.parts) {
        if ((part.quadTrianglesIndices.size() % 3) != 0 || (part.triangleIndices.size() % 3) != 0) {
            handleWarning("Found a mesh part with invalid index data, skipping");
            continue;
        }
        numTriangles += part.quadTrianglesIndices.size() / 3;
        numTriangles += part.triangleIndices.size() / 3;
    }

    if (numTriangles == 0) {
        return false;
    }

    draco::TriangleSoupMeshBuilder meshBuilder;

    meshBuilder.Start(numTriangles);

    bool hasNormals{ mesh.normals.size() > 0 };
    bool hasColors{ mesh.colors.size() > 0 };
    bool hasTexCoords{ mesh.texCoords.size() > 0 };
    bool hasTexCoords1{ mesh.texCoords1.size() > 0 };
    bool hasPerFaceMaterials = (materialIDCallback) ? (mesh.parts.size() > 1 || materialIDCallback(0) != 0 ) : true;
    bool needsOriginalIndices{ hasDeformers };

    int normalsAttributeID { -1 };
    int colorsAttributeID { -1 };
    int texCoordsAttributeID { -1 };
    int texCoords1AttributeID { -1 };
    int faceMaterialAttributeID { -1 };
    int originalIndexAttributeID { -1 };

    const int positionAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::POSITION,
                                                             3, draco::DT_FLOAT32);
    if (needsOriginalIndices) {
        originalIndexAttributeID = meshBuilder.AddAttribute(
            (draco::GeometryAttribute::Type)DRACO_ATTRIBUTE_ORIGINAL_INDEX,
            1, draco::DT_INT32);
    }

    if (hasNormals) {
        normalsAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::NORMAL,
                                                      3, draco::DT_FLOAT32);
    }
    if (hasColors) {
        colorsAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::COLOR,
                                                     3, draco::DT_FLOAT32);
    }
    if (hasTexCoords) {
        texCoordsAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::TEX_COORD,
                                                        2, draco::DT_FLOAT32);
    }
    if (hasTexCoords1) {
        texCoords1AttributeID = meshBuilder.AddAttribute(
            (draco::GeometryAttribute::Type)DRACO_ATTRIBUTE_TEX_COORD_1,
            2, draco::DT_FLOAT32);
    }
    if (hasPerFaceMaterials) {
        faceMaterialAttributeID = meshBuilder.AddAttribute(
            (draco::GeometryAttribute::Type)DRACO_ATTRIBUTE_MATERIAL_ID,
            1, draco::DT_UINT16);
    }

    auto partIndex = 0;
    draco::FaceIndex face;
    uint16_t materialID;
    
    for (auto& part : mesh.parts) {
        materialID = (materialIDCallback) ? materialIDCallback(partIndex) : partIndex;
        
        auto addFace = [&](QVector<int>& indices, int index, draco::FaceIndex face) {
            int32_t idx0 = indices[index];
            int32_t idx1 = indices[index + 1];
            int32_t idx2 = indices[index + 2];

            if (hasPerFaceMaterials) {
                meshBuilder.SetPerFaceAttributeValueForFace(faceMaterialAttributeID, face, &materialID);
            }

            meshBuilder.SetAttributeValuesForFace(positionAttributeID, face,
                                                  &mesh.vertices[idx0], &mesh.vertices[idx1],
                                                  &mesh.vertices[idx2]);

            if (needsOriginalIndices) {
                meshBuilder.SetAttributeValuesForFace(originalIndexAttributeID, face,
                                                      &mesh.originalIndices[idx0],
                                                      &mesh.originalIndices[idx1],
                                                      &mesh.originalIndices[idx2]);
            }
            if (hasNormals) {
                meshBuilder.SetAttributeValuesForFace(normalsAttributeID, face,
                                                      &mesh.normals[idx0], &mesh.normals[idx1],
                                                      &mesh.normals[idx2]);
            }
            if (hasColors) {
                meshBuilder.SetAttributeValuesForFace(colorsAttributeID, face,
                                                      &mesh.colors[idx0], &mesh.colors[idx1],
                                                      &mesh.colors[idx2]);
            }
            if (hasTexCoords) {
                meshBuilder.SetAttributeValuesForFace(texCoordsAttributeID, face,
                                                      &mesh.texCoords[idx0], &mesh.texCoords[idx1],
                                                      &mesh.texCoords[idx2]);
            }
            if (hasTexCoords1) {
                meshBuilder.SetAttributeValuesForFace(texCoords1AttributeID, face,
                                                      &mesh.texCoords1[idx0], &mesh.texCoords1[idx1],
                                                      &mesh.texCoords1[idx2]);
            }
        };

        for (int i = 0; (i + 2) < part.quadTrianglesIndices.size(); i += 3) {
            addFace(part.quadTrianglesIndices, i, face++);
        }

        for (int i = 0; (i + 2) < part.triangleIndices.size(); i += 3) {
            addFace(part.triangleIndices, i, face++);
        }

        partIndex++;
    }

    auto dracoMesh = meshBuilder.Finalize();

    if (!dracoMesh) {
        handleWarning("Failed to finalize the baking of a draco Geometry node");
        return false;
    }

    // we need to modify unique attribute IDs for custom attributes
    // so the attributes are easily retrievable on the other side
    if (hasPerFaceMaterials) {
        dracoMesh->attribute(faceMaterialAttributeID)->set_unique_id(DRACO_ATTRIBUTE_MATERIAL_ID);
    }

    if (hasTexCoords1) {
        dracoMesh->attribute(texCoords1AttributeID)->set_unique_id(DRACO_ATTRIBUTE_TEX_COORD_1);
    }

    if (needsOriginalIndices) {
        dracoMesh->attribute(originalIndexAttributeID)->set_unique_id(DRACO_ATTRIBUTE_ORIGINAL_INDEX);
    }

    draco::Encoder encoder;

    encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 14);
    encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, 12);
    encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, 10);
    encoder.SetSpeedOptions(0, 5);

    draco::EncoderBuffer buffer;
    encoder.EncodeMeshToBuffer(*dracoMesh, &buffer);

    FBXNode dracoNode;
    dracoNode.name = "DracoMesh";
    auto value = QVariant::fromValue(QByteArray(buffer.data(), (int)buffer.size()));
    dracoNode.properties.append(value);
    
    dracoMeshNode = dracoNode;
    // Mesh compression successful return true
    return true;
}