Andrew Meadowsfix comment5d5dc2810 years agoHistory
1348 lines · 52.9 KB · C++
RawDownload
    }    Extents modelMeshExtents = getUnscaledMeshExtents();     // size is our "target size in world space"    // we need to set our model scale so that the extents of the mesh, fit in a box that size...    glm::vec3 meshDimensions = modelMeshExtents.maximum - modelMeshExtents.minimum;    glm::vec3 rescaleDimensions = _scaleToFitDimensions / meshDimensions;    setScaleInternal(rescaleDimensions);    _scaledToFit = true;} void Model::setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint) {    glm::vec3 clampedRegistrationPoint = glm::clamp(registrationPoint, 0.0f, 1.0f);    if (_snapModelToRegistrationPoint != snapModelToRegistrationPoint || _registrationPoint != clampedRegistrationPoint) {        _snapModelToRegistrationPoint = snapModelToRegistrationPoint;        _registrationPoint = clampedRegistrationPoint;        _snappedToRegistrationPoint = false; // force re-centering    }} void Model::snapToRegistrationPoint() {    Extents modelMeshExtents = getUnscaledMeshExtents();    glm::vec3 dimensions = (modelMeshExtents.maximum - modelMeshExtents.minimum);    glm::vec3 offset = -modelMeshExtents.minimum - (dimensions * _registrationPoint);    _offset = offset;    _snappedToRegistrationPoint = true;} void Model::simulate(float deltaTime, bool fullUpdate) {    PROFILE_RANGE(__FUNCTION__);    fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)                    || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);     if (isActive() && fullUpdate) {        // NOTE: This is overly aggressive and we are invalidating the MeshBoxes when in fact they may not be invalid        //       they really only become invalid if something about the transform to world space has changed. This is        //       not too bad at this point, because it doesn't impact rendering. However it does slow down ray picking        //       because ray picking needs valid boxes to work        _calculatedMeshBoxesValid = false;        _calculatedMeshTrianglesValid = false;        onInvalidate();         // check for scale to fit        if (_scaleToFit && !_scaledToFit) {            scaleToFit();        }        if (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) {            snapToRegistrationPoint();        }        simulateInternal(deltaTime);    }} //virtualvoid Model::updateRig(float deltaTime, glm::mat4 parentTransform) {    _needsUpdateClusterMatrices = true;    _rig->updateAnimations(deltaTime, parentTransform);} void Model::simulateInternal(float deltaTime) {    // update the world space transforms for all joints    glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset);    updateRig(deltaTime, parentTransform);} // virtualvoid Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) {    PerformanceTimer perfTimer("Model::updateClusterMatrices");     if (!_needsUpdateClusterMatrices || !isLoaded()) {        return;    }    _needsUpdateClusterMatrices = false;    const FBXGeometry& geometry = getFBXGeometry();    glm::mat4 zeroScale(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),        glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),        glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),        glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));    auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;     glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);    for (int i = 0; i < _meshStates.size(); i++) {        MeshState& state = _meshStates[i];        const FBXMesh& mesh = geometry.meshes.at(i);         for (int j = 0; j < mesh.clusters.size(); j++) {            const FBXCluster& cluster = mesh.clusters.at(j);            auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);            state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;             // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.            if (!_cauterizeBoneSet.empty()) {                if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {                    jointMatrix = cauterizeMatrix;                }                state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;            }        }         // Once computed the cluster matrices, update the buffer(s)        if (mesh.clusters.size() > 1) {            if (!state.clusterBuffer) {                state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),                                                                    (const gpu::Byte*) state.clusterMatrices.constData());            } else {                state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),                                                (const gpu::Byte*) state.clusterMatrices.constData());            }             if (!_cauterizeBoneSet.empty() && (state.cauterizedClusterMatrices.size() > 1)) {                if (!state.cauterizedClusterBuffer) {                    state.cauterizedClusterBuffer =                        std::make_shared<gpu::Buffer>(state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),                                                      (const gpu::Byte*) state.cauterizedClusterMatrices.constData());                } else {                    state.cauterizedClusterBuffer->setSubData(0, state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),                                                              (const gpu::Byte*) state.cauterizedClusterMatrices.constData());                }            }        }    }     // post the blender if we're not currently waiting for one to finish    if (geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {        _blendedBlendshapeCoefficients = _blendshapeCoefficients;        DependencyManager::get<ModelBlender>()->noteRequiresBlend(getThisPointer());    }} void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority) {    const FBXGeometry& geometry = getFBXGeometry();    const QVector<int>& freeLineage = geometry.joints.at(endIndex).freeLineage;    glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset);    _rig->inverseKinematics(endIndex, targetPosition, targetRotation, priority, freeLineage, parentTransform);} bool Model::restoreJointPosition(int jointIndex, float fraction, float priority) {    const FBXGeometry& geometry = getFBXGeometry();    const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;    return _rig->restoreJointPosition(jointIndex, fraction, priority, freeLineage);} float Model::getLimbLength(int jointIndex) const {    const FBXGeometry& geometry = getFBXGeometry();    const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;    return _rig->getLimbLength(jointIndex, freeLineage, _scale, geometry.joints);} bool Model::maybeStartBlender() {    if (isLoaded()) {        const FBXGeometry& fbxGeometry = getFBXGeometry();        if (fbxGeometry.hasBlendedMeshes()) {            QThreadPool::globalInstance()->start(new Blender(getThisPointer(), ++_blendNumber, _geometry,                fbxGeometry.meshes, _blendshapeCoefficients));            return true;        }    }    return false;} void Model::setBlendedVertices(int blendNumber, const std::weak_ptr<NetworkGeometry>& geometry,        const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {    auto geometryRef = geometry.lock();    if (!geometryRef || _geometry != geometryRef || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) {        return;    }    _appliedBlendNumber = blendNumber;    const FBXGeometry& fbxGeometry = getFBXGeometry();    int index = 0;    for (int i = 0; i < fbxGeometry.meshes.size(); i++) {        const FBXMesh& mesh = fbxGeometry.meshes.at(i);        if (mesh.blendshapes.isEmpty()) {            continue;        }         gpu::BufferPointer& buffer = _blendedVertexBuffers[i];        buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Byte*) vertices.constData() + index*sizeof(glm::vec3));        buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3),            mesh.normals.size() * sizeof(glm::vec3), (gpu::Byte*) normals.constData() + index*sizeof(glm::vec3));         index += mesh.vertices.size();    }} void Model::deleteGeometry() {    _deleteGeometryCounter++;    _blendedVertexBuffers.clear();    _meshStates.clear();    _rig->destroyAnimGraph();    _blendedBlendshapeCoefficients.clear();} AABox Model::getRenderableMeshBound() const {    if (!isLoaded()) {        return AABox();    } else {        // Build a bound using the last known bound from all the renderItems.        AABox totalBound;        for (auto& renderItem : _modelMeshRenderItemsSet) {            totalBound += renderItem->getBound();        }        return totalBound;    }} void Model::segregateMeshGroups() {    NetworkGeometry::Pointer networkGeometry;    bool showingCollisionHull = false;    if (_showCollisionHull && _collisionGeometry) {        if (isCollisionLoaded()) {            networkGeometry = _collisionGeometry;            showingCollisionHull = true;        } else {            return;        }    } else {        assert(isLoaded());        networkGeometry = _geometry;    }    const FBXGeometry& geometry = networkGeometry->getGeometry()->getGeometry();    const auto& networkMeshes = networkGeometry->getGeometry()->getMeshes();     // all of our mesh vectors must match in size    auto geoMeshesSize = geometry.meshes.size();    if ((int)networkMeshes.size() != geoMeshesSize ||      //  geometry.meshes.size() != _meshStates.size()) {        geoMeshesSize > _meshStates.size()) {        qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet.";        return;    }     // We should not have any existing renderItems if we enter this section of code    Q_ASSERT(_modelMeshRenderItems.isEmpty());    Q_ASSERT(_modelMeshRenderItemsSet.isEmpty());    Q_ASSERT(_collisionRenderItems.isEmpty());    Q_ASSERT(_collisionRenderItemsSet.isEmpty());     _modelMeshRenderItemsSet.clear();    _collisionRenderItemsSet.clear();     Transform transform;    transform.setTranslation(_translation);    transform.setRotation(_rotation);     Transform offset;    offset.setScale(_scale);    offset.postTranslate(_offset);     // Run through all of the meshes, and place them into their segregated, but unsorted buckets    int shapeID = 0;    for (int i = 0; i < (int)networkMeshes.size(); i++) {        const FBXMesh& mesh = geometry.meshes.at(i);        const auto& networkMesh = networkMeshes.at(i);         // Create the render payloads        int totalParts = mesh.parts.size();        for (int partIndex = 0; partIndex < totalParts; partIndex++) {            if (showingCollisionHull) {                if (_collisionHullMaterials.empty()) {                    initCollisionHullMaterials();                }                _collisionRenderItemsSet << std::make_shared<MeshPartPayload>(networkMesh, partIndex, _collisionHullMaterials[partIndex % NUM_COLLISION_HULL_COLORS], transform, offset);            } else {                _modelMeshRenderItemsSet << std::make_shared<ModelMeshPartPayload>(this, i, partIndex, shapeID, transform, offset);            }             shapeID++;        }    }    _meshGroupsKnown = true;} bool Model::initWhenReady(render::ScenePointer scene) {    if (isActive() && isRenderable() && !_meshGroupsKnown && isLoaded()) {        segregateMeshGroups();         render::PendingChanges pendingChanges;         Transform transform;        transform.setTranslation(_translation);        transform.setRotation(_rotation);         Transform offset;        offset.setScale(_scale);        offset.postTranslate(_offset);         foreach (auto renderItem, _modelMeshRenderItemsSet) {            auto item = scene->allocateID();            auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);            _modelMeshRenderItems.insert(item, renderPayload);            pendingChanges.resetItem(item, renderPayload);        }        foreach (auto renderItem, _collisionRenderItemsSet) {            auto item = scene->allocateID();            auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem);            _collisionRenderItems.insert(item, renderPayload);            pendingChanges.resetItem(item, renderPayload);        }        scene->enqueuePendingChanges(pendingChanges);        updateRenderItems();         _readyWhenAdded = true;        return true;    }    return false;} ModelBlender::ModelBlender() :    _pendingBlenders(0) {} ModelBlender::~ModelBlender() {} void ModelBlender::noteRequiresBlend(ModelPointer model) {    if (_pendingBlenders < QThread::idealThreadCount()) {        if (model->maybeStartBlender()) {            _pendingBlenders++;        }        return;    }     {        Lock lock(_mutex);        _modelsRequiringBlends.insert(model);    }} void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber,        const std::weak_ptr<NetworkGeometry>& geometry, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {    if (model) {        model->setBlendedVertices(blendNumber, geometry, vertices, normals);    }    _pendingBlenders--;    {        Lock lock(_mutex);        for (auto i = _modelsRequiringBlends.begin(); i != _modelsRequiringBlends.end();) {            auto weakPtr = *i;            _modelsRequiringBlends.erase(i++); // remove front of the set            ModelPointer nextModel = weakPtr.lock();            if (nextModel && nextModel->maybeStartBlender()) {                _pendingBlenders++;                return;            }        }    }} 

Lines 1001–1348 of 1348. Previous lines