2157 lines · 87.4 KB · C++
RawDownload
////  Model.cpp//  interface/src/renderer////  Created by Andrzej Kapolka on 10/18/13.//  Copyright 2013 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include <gpu/GPUConfig.h> #include <QMetaType>#include <QRunnable>#include <QThreadPool> #include <glm/gtx/transform.hpp>#include <glm/gtx/norm.hpp> #include <CapsuleShape.h>#include <GeometryUtil.h>#include <gpu/Batch.h>#include <gpu/GLBackend.h>#include <PathUtils.h>#include <PerfStat.h>#include "PhysicsEntity.h"#include <ShapeCollider.h>#include <SphereShape.h>#include <ViewFrustum.h> #include "AbstractViewStateInterface.h"#include "AnimationHandle.h"#include "DeferredLightingEffect.h"#include "GlowEffect.h"#include "Model.h"#include "RenderUtilsLogging.h" #include "model_vert.h"#include "model_shadow_vert.h"#include "model_normal_map_vert.h"#include "model_lightmap_vert.h"#include "model_lightmap_normal_map_vert.h"#include "skin_model_vert.h"#include "skin_model_shadow_vert.h"#include "skin_model_normal_map_vert.h" #include "model_frag.h"#include "model_shadow_frag.h"#include "model_normal_map_frag.h"#include "model_normal_specular_map_frag.h"#include "model_specular_map_frag.h"#include "model_lightmap_frag.h"#include "model_lightmap_normal_map_frag.h"#include "model_lightmap_normal_specular_map_frag.h"#include "model_lightmap_specular_map_frag.h"#include "model_translucent_frag.h"  #define GLBATCH( call ) batch._##call//#define GLBATCH( call ) call using namespace std; static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; Model::Model(QObject* parent) :    QObject(parent),    _scale(1.0f, 1.0f, 1.0f),    _scaleToFit(false),    _scaleToFitDimensions(0.0f),    _scaledToFit(false),    _snapModelToRegistrationPoint(false),    _snappedToRegistrationPoint(false),    _showTrueJointTransforms(true),    _lodDistance(0.0f),    _pupilDilation(0.0f),    _url("http://invalid.com"),    _isVisible(true),    _blendNumber(0),    _appliedBlendNumber(0),    _calculatedMeshPartOffsetValid(false),    _calculatedMeshPartBoxesValid(false),    _calculatedMeshBoxesValid(false),    _calculatedMeshTrianglesValid(false),    _meshGroupsKnown(false),    _isWireframe(false),    _renderCollisionHull(false) {        // we may have been created in the network thread, but we live in the main thread    if (_viewState) {        moveToThread(_viewState->getMainThread());    }        setSnapModelToRegistrationPoint(true, glm::vec3(0.5f));} Model::~Model() {    deleteGeometry();} Model::RenderPipelineLib Model::_renderPipelineLib;const GLint MATERIAL_GPU_SLOT = 3; void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,                                                 gpu::ShaderPointer& vertexShader,                                                 gpu::ShaderPointer& pixelShader ) {     gpu::Shader::BindingSet slotBindings;    slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));    slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0));    slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1));    slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));    slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3));    slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4));     gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));    gpu::Shader::makeProgram(*program, slotBindings);            auto locations = std::shared_ptr<Locations>(new Locations());    initLocations(program, *locations);         gpu::StatePointer state = gpu::StatePointer(new gpu::State());     // Backface on shadow    if (key.isShadow()) {        state->setCullMode(gpu::State::CULL_FRONT);        state->setDepthBias(1.0f);        state->setDepthBiasSlopeScale(4.0f);    } else {        state->setCullMode(gpu::State::CULL_BACK);    }     // Z test depends if transparent or not    state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);     // Blend on transparent    state->setBlendFunction(key.isTranslucent(),        gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, // For transparent only, this keep the highlight intensity        gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);     // Good to go add the brand new pipeline    auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));    insert(value_type(key.getRaw(), RenderPipeline(pipeline, locations)));            if (!key.isWireFrame()) {                RenderKey wireframeKey(key.getRaw() | RenderKey::IS_WIREFRAME);        gpu::StatePointer wireframeState = gpu::StatePointer(new gpu::State(state->getValues()));                wireframeState->setFillMode(gpu::State::FILL_LINE);                // create a new RenderPipeline with the same shader side and the mirrorState        auto wireframePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, wireframeState));        insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations)));    }        // If not a shadow pass, create the mirror version from the same state, just change the FrontFace    if (!key.isShadow()) {                RenderKey mirrorKey(key.getRaw() | RenderKey::IS_MIRROR);        gpu::StatePointer mirrorState = gpu::StatePointer(new gpu::State(state->getValues()));         mirrorState->setFrontFaceClockwise(true);         // create a new RenderPipeline with the same shader side and the mirrorState        auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState));        insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations)));                if (!key.isWireFrame()) {            RenderKey wireframeKey(key.getRaw() | RenderKey::IS_MIRROR | RenderKey::IS_WIREFRAME);            gpu::StatePointer wireframeState = gpu::StatePointer(new gpu::State(state->getValues()));;                        wireframeState->setFillMode(gpu::State::FILL_LINE);                        // create a new RenderPipeline with the same shader side and the mirrorState            auto wireframePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, wireframeState));            insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations)));        }    }}  void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model::Locations& locations) {    locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold");    locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices");    locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");    locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");     locations.specularTextureUnit = program->getTextures().findLocation("specularMap");    locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); #if (GPU_FEATURE_PROFILE == GPU_CORE)    locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer");    locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer");#else    locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer");    locations.lightBufferUnit = program->getUniforms().findLocation("lightBuffer");#endif    locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices");     locations.clusterIndices = program->getInputs().findLocation("clusterIndices");;    locations.clusterWeights = program->getInputs().findLocation("clusterWeights");;      } AbstractViewStateInterface* Model::_viewState = NULL;  void Model::setScale(const glm::vec3& scale) {    setScaleInternal(scale);    // if anyone sets scale manually, then we are no longer scaled to fit    _scaleToFit = false;    _scaledToFit = false;} void Model::setScaleInternal(const glm::vec3& scale) {    float scaleLength = glm::length(_scale);    float relativeDeltaScale = glm::length(_scale - scale) / scaleLength;     const float ONE_PERCENT = 0.01f;    if (relativeDeltaScale > ONE_PERCENT || scaleLength < EPSILON) {        _scale = scale;        initJointTransforms();        if (_shapes.size() > 0) {            clearShapes();            buildShapes();        }    }} void Model::setOffset(const glm::vec3& offset) {     _offset = offset;         // if someone manually sets our offset, then we are no longer snapped to center    _snapModelToRegistrationPoint = false;     _snappedToRegistrationPoint = false; } QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {    QVector<JointState> jointStates;    for (int i = 0; i < geometry.joints.size(); ++i) {        const FBXJoint& joint = geometry.joints[i];        // store a pointer to the FBXJoint in the JointState        JointState state;        state.setFBXJoint(&joint);         jointStates.append(state);    }    return jointStates;}; void Model::initJointTransforms() {    // compute model transforms    int numStates = _jointStates.size();    for (int i = 0; i < numStates; ++i) {        JointState& state = _jointStates[i];        const FBXJoint& joint = state.getFBXJoint();        int parentIndex = joint.parentIndex;        if (parentIndex == -1) {            const FBXGeometry& geometry = _geometry->getFBXGeometry();            // NOTE: in practice geometry.offset has a non-unity scale (rather than a translation)            glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;            state.initTransform(parentTransform);        } else {            const JointState& parentState = _jointStates.at(parentIndex);            state.initTransform(parentState.getTransform());        }    }} void Model::init() {    if (_renderPipelineLib.empty()) {        // Vertex shaders        auto modelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert)));        auto modelNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_normal_map_vert)));        auto modelLightmapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_lightmap_vert)));        auto modelLightmapNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)));        auto modelShadowVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_shadow_vert)));        auto skinModelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(skin_model_vert)));        auto skinModelNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)));        auto skinModelShadowVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(skin_model_shadow_vert)));         // Pixel shaders        auto modelPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_frag)));        auto modelNormalMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_normal_map_frag)));        auto modelSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_specular_map_frag)));        auto modelNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)));        auto modelTranslucentPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_translucent_frag)));        auto modelShadowPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_shadow_frag)));        auto modelLightmapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_frag)));        auto modelLightmapNormalMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)));        auto modelLightmapSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)));        auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)));         // Fill the renderPipelineLib                _renderPipelineLib.addRenderPipeline(            RenderKey(0),            modelVertex, modelPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_TANGENTS),            modelNormalMapVertex, modelNormalMapPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_SPECULAR),            modelVertex, modelSpecularMapPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),            modelNormalMapVertex, modelNormalSpecularMapPixel);                 _renderPipelineLib.addRenderPipeline(             RenderKey(RenderKey::IS_TRANSLUCENT),             modelVertex, modelTranslucentPixel);        // FIXME Ignore lightmap for translucents meshpart        _renderPipelineLib.addRenderPipeline(             RenderKey(RenderKey::IS_TRANSLUCENT | RenderKey::HAS_LIGHTMAP),             modelVertex, modelTranslucentPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT),            modelNormalMapVertex, modelTranslucentPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT),            modelVertex, modelTranslucentPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT),            modelNormalMapVertex, modelTranslucentPixel);          _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_LIGHTMAP),            modelLightmapVertex, modelLightmapPixel);        _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS),            modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_SPECULAR),            modelLightmapVertex, modelLightmapSpecularMapPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),            modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);          _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED),            skinModelVertex, modelPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS),            skinModelNormalMapVertex, modelNormalMapPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR),            skinModelVertex, modelSpecularMapPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),            skinModelNormalMapVertex, modelNormalSpecularMapPixel);          _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT),            skinModelVertex, modelTranslucentPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT),            skinModelNormalMapVertex, modelTranslucentPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT),            skinModelVertex, modelTranslucentPixel);         _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT),            skinModelNormalMapVertex, modelTranslucentPixel);          _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),            modelShadowVertex, modelShadowPixel);          _renderPipelineLib.addRenderPipeline(            RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),            skinModelShadowVertex, modelShadowPixel);    }} void Model::reset() {    if (_jointStates.isEmpty()) {        return;    }    const FBXGeometry& geometry = _geometry->getFBXGeometry();    for (int i = 0; i < _jointStates.size(); i++) {        _jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation, 0.0f);    }        _meshGroupsKnown = false;    _readyWhenAdded = false; // in case any of our users are using scenes    invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid} bool Model::updateGeometry() {    bool needFullUpdate = false;     bool needToRebuild = false;    if (_nextGeometry) {        _nextGeometry = _nextGeometry->getLODOrFallback(_lodDistance, _nextLODHysteresis);        _nextGeometry->setLoadPriority(this, -_lodDistance);        _nextGeometry->ensureLoading();        if (_nextGeometry->isLoaded()) {            applyNextGeometry();            needToRebuild = true;        }    }    if (!_geometry) {        // geometry is not ready        return false;    }     QSharedPointer<NetworkGeometry> geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis);    if (_geometry != geometry) {         // NOTE: it is theoretically impossible to reach here after passing through the applyNextGeometry() call above.        // Which means we don't need to worry about calling deleteGeometry() below immediately after creating new geometry.         const FBXGeometry& newGeometry = geometry->getFBXGeometry();        QVector<JointState> newJointStates = createJointStates(newGeometry);        if (! _jointStates.isEmpty()) {            // copy the existing joint states            const FBXGeometry& oldGeometry = _geometry->getFBXGeometry();            for (QHash<QString, int>::const_iterator it = oldGeometry.jointIndices.constBegin();                    it != oldGeometry.jointIndices.constEnd(); it++) {                int oldIndex = it.value() - 1;                int newIndex = newGeometry.getJointIndex(it.key());                if (newIndex != -1) {                    newJointStates[newIndex].copyState(_jointStates[oldIndex]);                }            }        }         deleteGeometry();        _dilatedTextures.clear();        _geometry = geometry;        _meshGroupsKnown = false;        _readyWhenAdded = false; // in case any of our users are using scenes        invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid        initJointStates(newJointStates);        needToRebuild = true;    } else if (_jointStates.isEmpty()) {        const FBXGeometry& fbxGeometry = geometry->getFBXGeometry();        if (fbxGeometry.joints.size() > 0) {            initJointStates(createJointStates(fbxGeometry));            needToRebuild = true;        }    } else if (!geometry->isLoaded()) {        deleteGeometry();        _dilatedTextures.clear();    }    _geometry->setLoadPriority(this, -_lodDistance);    _geometry->ensureLoading();       if (needToRebuild) {        const FBXGeometry& fbxGeometry = geometry->getFBXGeometry();        foreach (const FBXMesh& mesh, fbxGeometry.meshes) {            MeshState state;            state.clusterMatrices.resize(mesh.clusters.size());            _meshStates.append(state);                 gpu::BufferPointer buffer(new gpu::Buffer());            if (!mesh.blendshapes.isEmpty()) {                buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));                buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.vertices.constData());                buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3),                    mesh.normals.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.normals.constData());            }            _blendedVertexBuffers.push_back(buffer);        }        needFullUpdate = true;    }    return needFullUpdate;} // virtualvoid Model::initJointStates(QVector<JointState> states) {

Lines 1–500 of 2157.