1753 lines · 71.5 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 <QMetaType>#include <QRunnable>#include <QScriptEngine>#include <QThreadPool> #include <glm/gtx/transform.hpp>#include <glm/gtx/norm.hpp> #include <CapsuleShape.h>#include <GeometryUtil.h>#include <PhysicsEntity.h>#include <RegisteredMetaTypes.h>#include <ShapeCollider.h>#include <SphereShape.h> #include "Application.h"#include "Model.h" using namespace std; static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >(); static QScriptValue localLightToScriptValue(QScriptEngine* engine, const Model::LocalLight& light) {    QScriptValue object = engine->newObject();    object.setProperty("direction", vec3toScriptValue(engine, light.direction));    object.setProperty("color", vec3toScriptValue(engine, light.color));    return object;} static void localLightFromScriptValue(const QScriptValue& value, Model::LocalLight& light) {    vec3FromScriptValue(value.property("direction"), light.direction);    vec3FromScriptValue(value.property("color"), light.color);} void Model::registerMetaTypes(QScriptEngine* engine) {    qScriptRegisterMetaType(engine, localLightToScriptValue, localLightFromScriptValue);    qScriptRegisterSequenceMetaType<QVector<Model::LocalLight> >(engine);} Model::Model(QObject* parent) :    QObject(parent),    _scale(1.0f, 1.0f, 1.0f),    _scaleToFit(false),    _scaleToFitLargestDimension(0.0f),    _scaledToFit(false),    _snapModelToCenter(false),    _snappedToCenter(false),    _showTrueJointTransforms(true),    _lodDistance(0.0f),    _pupilDilation(0.0f),    _url("http://invalid.com") {    // we may have been created in the network thread, but we live in the main thread    moveToThread(Application::getInstance()->thread());} Model::~Model() {    deleteGeometry();} ProgramObject Model::_program;ProgramObject Model::_normalMapProgram;ProgramObject Model::_specularMapProgram;ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_shadowMapProgram;ProgramObject Model::_shadowNormalMapProgram;ProgramObject Model::_shadowSpecularMapProgram;ProgramObject Model::_shadowNormalSpecularMapProgram; ProgramObject Model::_cascadedShadowMapProgram;ProgramObject Model::_cascadedShadowNormalMapProgram;ProgramObject Model::_cascadedShadowSpecularMapProgram;ProgramObject Model::_cascadedShadowNormalSpecularMapProgram; ProgramObject Model::_shadowProgram; ProgramObject Model::_skinProgram;ProgramObject Model::_skinNormalMapProgram;ProgramObject Model::_skinSpecularMapProgram;ProgramObject Model::_skinNormalSpecularMapProgram; ProgramObject Model::_skinShadowMapProgram;ProgramObject Model::_skinShadowNormalMapProgram;ProgramObject Model::_skinShadowSpecularMapProgram;ProgramObject Model::_skinShadowNormalSpecularMapProgram; ProgramObject Model::_skinCascadedShadowMapProgram;ProgramObject Model::_skinCascadedShadowNormalMapProgram;ProgramObject Model::_skinCascadedShadowSpecularMapProgram;ProgramObject Model::_skinCascadedShadowNormalSpecularMapProgram; ProgramObject Model::_skinShadowProgram; Model::Locations Model::_locations;Model::Locations Model::_normalMapLocations;Model::Locations Model::_specularMapLocations;Model::Locations Model::_normalSpecularMapLocations;Model::Locations Model::_shadowMapLocations;Model::Locations Model::_shadowNormalMapLocations;Model::Locations Model::_shadowSpecularMapLocations;Model::Locations Model::_shadowNormalSpecularMapLocations;Model::Locations Model::_cascadedShadowMapLocations;Model::Locations Model::_cascadedShadowNormalMapLocations;Model::Locations Model::_cascadedShadowSpecularMapLocations;Model::Locations Model::_cascadedShadowNormalSpecularMapLocations;    Model::SkinLocations Model::_skinLocations;Model::SkinLocations Model::_skinNormalMapLocations;Model::SkinLocations Model::_skinSpecularMapLocations;Model::SkinLocations Model::_skinNormalSpecularMapLocations;Model::SkinLocations Model::_skinShadowMapLocations;Model::SkinLocations Model::_skinShadowNormalMapLocations;Model::SkinLocations Model::_skinShadowSpecularMapLocations;Model::SkinLocations Model::_skinShadowNormalSpecularMapLocations;Model::SkinLocations Model::_skinCascadedShadowMapLocations;Model::SkinLocations Model::_skinCascadedShadowNormalMapLocations;Model::SkinLocations Model::_skinCascadedShadowSpecularMapLocations;Model::SkinLocations Model::_skinCascadedShadowNormalSpecularMapLocations;Model::SkinLocations Model::_skinShadowLocations; 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    _snapModelToCenter = false;     _snappedToCenter = false; } void Model::initProgram(ProgramObject& program, Model::Locations& locations,        int specularTextureUnit, int shadowTextureUnit) {    program.bind();    locations.tangent = program.attributeLocation("tangent");    locations.shadowDistances = program.uniformLocation("shadowDistances");    locations.localLightColors = program.uniformLocation("localLightColors");    locations.localLightDirections = program.uniformLocation("localLightDirections");    program.setUniformValue("diffuseMap", 0);    program.setUniformValue("normalMap", 1);    program.setUniformValue("specularMap", specularTextureUnit);    program.setUniformValue("shadowMap", shadowTextureUnit);    program.release();} void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations,        int specularTextureUnit, int shadowTextureUnit) {    initProgram(program, locations, specularTextureUnit, shadowTextureUnit);        program.bind();    locations.clusterMatrices = program.uniformLocation("clusterMatrices");    locations.clusterIndices = program.attributeLocation("clusterIndices");    locations.clusterWeights = program.attributeLocation("clusterWeights");    program.release();} 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 (!_program.isLinked()) {        _program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert");        _program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag");        _program.link();                initProgram(_program, _locations);                _normalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model_normal_map.vert");        _normalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_normal_map.frag");        _normalMapProgram.link();                initProgram(_normalMapProgram, _normalMapLocations);                _specularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model.vert");        _specularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_specular_map.frag");        _specularMapProgram.link();                initProgram(_specularMapProgram, _specularMapLocations);                _normalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model_normal_map.vert");        _normalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_normal_specular_map.frag");        _normalSpecularMapProgram.link();                initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations, 2);                        _shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert");        _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/model_shadow_map.frag");        _shadowMapProgram.link();                initProgram(_shadowMapProgram, _shadowMapLocations);                _shadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model_normal_map.vert");        _shadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow_normal_map.frag");        _shadowNormalMapProgram.link();                initProgram(_shadowNormalMapProgram, _shadowNormalMapLocations, 1, 2);                _shadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model.vert");        _shadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow_specular_map.frag");        _shadowSpecularMapProgram.link();                initProgram(_shadowSpecularMapProgram, _shadowSpecularMapLocations, 1, 2);                _shadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model_normal_map.vert");        _shadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow_normal_specular_map.frag");        _shadowNormalSpecularMapProgram.link();                initProgram(_shadowNormalSpecularMapProgram, _shadowNormalSpecularMapLocations, 2, 3);                        _cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/model.vert");        _cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/model_cascaded_shadow_map.frag");        _cascadedShadowMapProgram.link();                initProgram(_cascadedShadowMapProgram, _cascadedShadowMapLocations);                _cascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model_normal_map.vert");        _cascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_map.frag");        _cascadedShadowNormalMapProgram.link();                initProgram(_cascadedShadowNormalMapProgram, _cascadedShadowNormalMapLocations, 1, 2);                _cascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model.vert");        _cascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_cascaded_shadow_specular_map.frag");        _cascadedShadowSpecularMapProgram.link();                initProgram(_cascadedShadowSpecularMapProgram, _cascadedShadowSpecularMapLocations, 1, 2);                _cascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/model_normal_map.vert");        _cascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_specular_map.frag");        _cascadedShadowNormalSpecularMapProgram.link();                initProgram(_cascadedShadowNormalSpecularMapProgram, _cascadedShadowNormalSpecularMapLocations, 2, 3);                        _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert");        _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow.frag");        _shadowProgram.link();                        _skinProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert");        _skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag");        _skinProgram.link();                initSkinProgram(_skinProgram, _skinLocations);                _skinNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model_normal_map.vert");        _skinNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_normal_map.frag");        _skinNormalMapProgram.link();                initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations);                _skinSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model.vert");        _skinSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_specular_map.frag");        _skinSpecularMapProgram.link();                initSkinProgram(_skinSpecularMapProgram, _skinSpecularMapLocations);                _skinNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model_normal_map.vert");        _skinNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_normal_specular_map.frag");        _skinNormalSpecularMapProgram.link();                initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations, 2);                        _skinShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/skin_model.vert");        _skinShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/model_shadow_map.frag");        _skinShadowMapProgram.link();                initSkinProgram(_skinShadowMapProgram, _skinShadowMapLocations);                _skinShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model_normal_map.vert");        _skinShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow_normal_map.frag");        _skinShadowNormalMapProgram.link();                initSkinProgram(_skinShadowNormalMapProgram, _skinShadowNormalMapLocations, 1, 2);                _skinShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model.vert");        _skinShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow_specular_map.frag");        _skinShadowSpecularMapProgram.link();                initSkinProgram(_skinShadowSpecularMapProgram, _skinShadowSpecularMapLocations, 1, 2);                _skinShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model_normal_map.vert");        _skinShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow_normal_specular_map.frag");        _skinShadowNormalSpecularMapProgram.link();                initSkinProgram(_skinShadowNormalSpecularMapProgram, _skinShadowNormalSpecularMapLocations, 2, 3);                        _skinCascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/skin_model.vert");        _skinCascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/model_cascaded_shadow_map.frag");        _skinCascadedShadowMapProgram.link();                initSkinProgram(_skinCascadedShadowMapProgram, _skinCascadedShadowMapLocations);                _skinCascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model_normal_map.vert");        _skinCascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_map.frag");        _skinCascadedShadowNormalMapProgram.link();                initSkinProgram(_skinCascadedShadowNormalMapProgram, _skinCascadedShadowNormalMapLocations, 1, 2);                _skinCascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model.vert");        _skinCascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_cascaded_shadow_specular_map.frag");        _skinCascadedShadowSpecularMapProgram.link();                initSkinProgram(_skinCascadedShadowSpecularMapProgram, _skinCascadedShadowSpecularMapLocations, 1, 2);                _skinCascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model_normal_map.vert");        _skinCascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_specular_map.frag");        _skinCascadedShadowNormalSpecularMapProgram.link();                initSkinProgram(_skinCascadedShadowNormalSpecularMapProgram, _skinCascadedShadowNormalSpecularMapLocations, 2, 3);                        _skinShadowProgram.addShaderFromSourceFile(QGLShader::Vertex,            Application::resourcesPath() + "shaders/skin_model_shadow.vert");        _skinShadowProgram.addShaderFromSourceFile(QGLShader::Fragment,            Application::resourcesPath() + "shaders/model_shadow.frag");        _skinShadowProgram.link();                initSkinProgram(_skinShadowProgram, _skinShadowLocations);    }} void Model::reset() {    if (_jointStates.isEmpty()) {        return;    }    foreach (Model* attachment, _attachments) {        attachment->reset();    }    const FBXGeometry& geometry = _geometry->getFBXGeometry();    for (int i = 0; i < _jointStates.size(); i++) {        _jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation);    }} bool Model::updateGeometry() {    // NOTE: this is a recursive call that walks all attachments, and their attachments    bool needFullUpdate = false;    for (int i = 0; i < _attachments.size(); i++) {        Model* model = _attachments.at(i);        if (model->updateGeometry()) {            needFullUpdate = true;        }    }     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;        setJointStates(newJointStates);        needToRebuild = true;    } else if (_jointStates.isEmpty()) {        const FBXGeometry& fbxGeometry = geometry->getFBXGeometry();        if (fbxGeometry.joints.size() > 0) {            setJointStates(createJointStates(fbxGeometry));            needToRebuild = true;        }    } else if (!geometry->isLoaded()) {

Lines 1–500 of 1753.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t