From 7c8d52cbd15f3f5b2f052703aeeac1c8e9108466 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 22 Jul 2015 13:41:31 -0700 Subject: [PATCH] back out some changes to Model.cpp, change how rig pointer is delivered to model initilizer --- interface/src/avatar/Avatar.cpp | 4 +- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/AvatarManager.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 8 +- interface/src/avatar/MyAvatar.h | 2 +- interface/src/avatar/SkeletonModel.cpp | 9 +- interface/src/avatar/SkeletonModel.h | 2 +- libraries/animation/src/Rig.cpp | 15 +- libraries/animation/src/Rig.h | 4 +- libraries/render-utils/src/Model.cpp | 521 +++++++++---------------- libraries/render-utils/src/Model.h | 13 +- tools/vhacd-util/src/VHACDUtil.cpp | 2 + 12 files changed, 228 insertions(+), 358 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 3a55e73fa6..1d14a0f464 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -75,9 +75,9 @@ namespace render { } } -Avatar::Avatar() : +Avatar::Avatar(RigPointer rig) : AvatarData(), - _skeletonModel(this), + _skeletonModel(this, nullptr, rig), _skeletonOffset(0.0f), _bodyYawDelta(0.0f), _positionDeltaAccumulator(0.0f), diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ae99317541..096af5c229 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -72,7 +72,7 @@ class Avatar : public AvatarData { Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset) public: - Avatar(); + Avatar(RigPointer rig = nullptr); ~Avatar(); typedef render::Payload Payload; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d5922366e9..730c77e9c3 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -65,7 +65,7 @@ AvatarManager::AvatarManager(QObject* parent) : { // register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar qRegisterMetaType >("NodeWeakPointer"); - _myAvatar = std::make_shared(); + _myAvatar = std::make_shared(std::make_shared()); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket"); @@ -160,7 +160,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { } AvatarSharedPointer AvatarManager::newSharedAvatar() { - return AvatarSharedPointer(std::make_shared()); + return AvatarSharedPointer(std::make_shared(std::make_shared())); } // virtual diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c59f92f33f..b59d605752 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -78,8 +78,8 @@ const float MyAvatar::ZOOM_MIN = 0.5f; const float MyAvatar::ZOOM_MAX = 25.0f; const float MyAvatar::ZOOM_DEFAULT = 1.5f; -MyAvatar::MyAvatar() : - Avatar(), +MyAvatar::MyAvatar(RigPointer rig) : + Avatar(rig), _gravity(0.0f, 0.0f, 0.0f), _wasPushing(false), _isPushing(false), @@ -102,8 +102,8 @@ MyAvatar::MyAvatar() : _eyeContactTarget(LEFT_EYE), _realWorldFieldOfView("realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), - _rig(new Rig()), - _firstPersonSkeletonModel(this, nullptr, _rig), + _rig(rig), + _firstPersonSkeletonModel(this, nullptr, rig), _prevShouldDrawHead(true) { _firstPersonSkeletonModel.setIsFirstPerson(true); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d2c3ee9ab0..ba84ab0e96 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -36,7 +36,7 @@ class MyAvatar : public Avatar { //TODO: make gravity feature work Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setGravity) public: - MyAvatar(); + MyAvatar(RigPointer rig); ~MyAvatar(); QByteArray toByteArray(); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 551d616732..c8e6f03d69 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -42,6 +42,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer r _headClipDistance(DEFAULT_NEAR_CLIP), _isFirstPerson(false) { + assert(_rig); assert(_owningAvatar); _enableShapes = true; } @@ -269,7 +270,6 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { } } - void SkeletonModel::updateJointState(int index) { if (index < 0 && index >= _jointStates.size()) { return; // bail @@ -281,10 +281,10 @@ void SkeletonModel::updateJointState(int index) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (index == geometry.leanJointIndex) { maybeUpdateLeanRotation(parentState, state); - + } else if (index == geometry.neckJointIndex) { - maybeUpdateNeckRotation(parentState, joint, state); - + maybeUpdateNeckRotation(parentState, joint, state); + } else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) { maybeUpdateEyeRotation(parentState, joint, state); } @@ -297,7 +297,6 @@ void SkeletonModel::updateJointState(int index) { } } - void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, JointState& state) { if (!_owningAvatar->isMyAvatar()) { return; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index ae8ffe66a9..6d33b3da7b 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -161,7 +161,7 @@ private: void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation); bool getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; - + Avatar* _owningAvatar; CapsuleShape _boundingShape; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index a76c866140..5e322e420f 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -184,17 +184,28 @@ void Rig::resetAllTransformsChanged() { } } -glm::quat Rig::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority) { +glm::quat Rig::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority, bool constrain) { glm::quat endRotation; if (jointIndex == -1 || _jointStates.isEmpty()) { return endRotation; } JointState& state = _jointStates[jointIndex]; - state.setRotationInBindFrame(rotation, priority); + state.setRotationInBindFrame(rotation, priority, constrain); endRotation = state.getRotationInBindFrame(); return endRotation; } +glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, bool constrain) { + glm::quat endRotation; + if (jointIndex == -1 || _jointStates.isEmpty()) { + return endRotation; + } + JointState& state = _jointStates[jointIndex]; + state.setRotationInConstrainedFrame(targetRotation, priority, constrain); + endRotation = state.getRotationInConstrainedFrame(); + return endRotation; +} + void Rig::applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 552601f44f..b1155cbb9d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -54,7 +54,9 @@ public: void clearJointStates(); void setJointState(int index, bool valid, const glm::quat& rotation, float priority); void clearJointAnimationPriority(int index); - glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority); + glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority, bool constrain = false); + glm::quat setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, + float priority, bool constrain = false); void applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority); QVector getJointStates() { return _jointStates; } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index df805e4d29..5a6908fc4a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -83,12 +83,11 @@ Model::Model(QObject* parent, RigPointer rig) : _isWireframe(false), _renderCollisionHull(false), _rig(rig) { - // 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)); } @@ -113,12 +112,14 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); gpu::Shader::makeProgram(*program, slotBindings); - + + auto locations = std::make_shared(); initLocations(program, *locations); + auto state = std::make_shared(); - + // Backface on shadow if (key.isShadow()) { state->setCullMode(gpu::State::CULL_FRONT); @@ -133,35 +134,29 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, // 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); + 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); -<<<<<<< HEAD - gpu::StatePointer wireframeState = gpu::StatePointer(new gpu::State(state->getValues())); - -======= auto wireframeState = std::make_shared(state->getValues()); ->>>>>>> cf88bce0820df76a55473370db0fcb8c5fe6763d 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); auto mirrorState = std::make_shared(state->getValues()); @@ -170,18 +165,13 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, // 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); -<<<<<<< HEAD - gpu::StatePointer wireframeState = gpu::StatePointer(new gpu::State(state->getValues()));; - -======= auto wireframeState = std::make_shared(state->getValues()); ->>>>>>> cf88bce0820df76a55473370db0fcb8c5fe6763d 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))); @@ -210,7 +200,7 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model: locations.clusterIndices = program->getInputs().findLocation("clusterIndices");; locations.clusterWeights = program->getInputs().findLocation("clusterWeights");; - + } @@ -240,12 +230,12 @@ void Model::setScaleInternal(const glm::vec3& scale) { } } -void Model::setOffset(const glm::vec3& offset) { - _offset = offset; - +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; + _snapModelToRegistrationPoint = false; + _snappedToRegistrationPoint = false; } QVector Model::createJointStates(const FBXGeometry& geometry) { @@ -262,24 +252,20 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { }; void Model::initJointTransforms() { - if (_rig) { - _rig->initJointTransforms(_scale, _offset); - } else { - // 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()); - } + // 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()); } } } @@ -309,7 +295,7 @@ void Model::init() { auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag))); // Fill the renderPipelineLib - + _renderPipelineLib.addRenderPipeline( RenderKey(0), modelVertex, modelPixel); @@ -326,7 +312,7 @@ void Model::init() { RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), modelNormalMapVertex, modelNormalSpecularMapPixel); - + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_TRANSLUCENT), modelVertex, modelTranslucentPixel); @@ -334,7 +320,7 @@ void Model::init() { _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_TRANSLUCENT | RenderKey::HAS_LIGHTMAP), modelVertex, modelTranslucentPixel); - + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), modelNormalMapVertex, modelTranslucentPixel); @@ -410,18 +396,14 @@ void Model::init() { } void Model::reset() { - if (_rig) { - _rig->resetJoints(); - } else { - 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); - } + 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 @@ -446,8 +428,6 @@ bool Model::updateGeometry() { return false; } - bool jointStatesEmpty = _rig ? _rig->jointStatesEmpty() : _jointStates.isEmpty(); - QSharedPointer geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis); if (_geometry != geometry) { @@ -456,7 +436,7 @@ bool Model::updateGeometry() { const FBXGeometry& newGeometry = geometry->getFBXGeometry(); QVector newJointStates = createJointStates(newGeometry); - if (! jointStatesEmpty) { + if (! _jointStates.isEmpty()) { // copy the existing joint states const FBXGeometry& oldGeometry = _geometry->getFBXGeometry(); for (QHash::const_iterator it = oldGeometry.jointIndices.constBegin(); @@ -464,24 +444,20 @@ bool Model::updateGeometry() { int oldIndex = it.value() - 1; int newIndex = newGeometry.getJointIndex(it.key()); if (newIndex != -1) { - JointState jointState; - if (!getJointStateAtIndex(oldIndex, jointState)) { - return false; - } - newJointStates[newIndex].copyState(jointState); + newJointStates[newIndex].copyState(_jointStates[oldIndex]); } } - } + } deleteGeometry(); _dilatedTextures.clear(); setGeometry(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 (jointStatesEmpty) { + } else if (_jointStates.isEmpty()) { const FBXGeometry& fbxGeometry = geometry->getFBXGeometry(); if (fbxGeometry.joints.size() > 0) { initJointStates(createJointStates(fbxGeometry)); @@ -493,21 +469,15 @@ bool Model::updateGeometry() { } _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()); -<<<<<<< HEAD - _meshStates.append(state); - - gpu::BufferPointer buffer(new gpu::Buffer()); -======= _meshStates.append(state); auto buffer = std::make_shared(); ->>>>>>> cf88bce0820df76a55473370db0fcb8c5fe6763d 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()); @@ -523,29 +493,25 @@ bool Model::updateGeometry() { // virtual void Model::initJointStates(QVector states) { - if (_rig) { - _boundingRadius = _rig->initJointStates(_scale, _offset, states); - } else { - _jointStates = states; - initJointTransforms(); + _jointStates = states; + initJointTransforms(); - int numStates = _jointStates.size(); - float radius = 0.0f; - for (int i = 0; i < numStates; ++i) { - float distance = glm::length(_jointStates[i].getPosition()); - if (distance > radius) { - radius = distance; - } - _jointStates[i].buildConstraint(); + int numStates = _jointStates.size(); + float radius = 0.0f; + for (int i = 0; i < numStates; ++i) { + float distance = glm::length(_jointStates[i].getPosition()); + if (distance > radius) { + radius = distance; } - for (int i = 0; i < _jointStates.size(); i++) { - _jointStates[i].slaveVisibleTransform(); - } - _boundingRadius = radius; + _jointStates[i].buildConstraint(); } + for (int i = 0; i < _jointStates.size(); i++) { + _jointStates[i].slaveVisibleTransform(); + } + _boundingRadius = radius; } -bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, +bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { bool intersectedSomething = false; @@ -554,7 +520,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (!isActive()) { return intersectedSomething; } - + // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); @@ -563,7 +529,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated - + glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference AABox modelFrameBox(corner, dimensions); @@ -602,7 +568,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g int t = 0; foreach (const Triangle& triangle, meshTriangles) { t++; - + float thisTriangleDistance; if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) { if (thisTriangleDistance < bestDistance) { @@ -621,7 +587,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } } - } + } subMeshIndex++; } _mutex.unlock(); @@ -629,7 +595,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (intersectedSomething) { distance = bestDistance; } - + return intersectedSomething; } @@ -641,22 +607,22 @@ bool Model::convexHullContains(glm::vec3 point) { if (!isActive()) { return false; } - + // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); glm::mat4 translation = glm::translate(position); glm::mat4 modelToWorldMatrix = translation * rotation; glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); - + Extents modelExtents = getMeshExtents(); // NOTE: unrotated - + glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = -(dimensions * _registrationPoint); AABox modelFrameBox(corner, dimensions); - + glm::vec3 modelFramePoint = glm::vec3(worldToModelMatrix * glm::vec4(point, 1.0f)); - + // we can use the AABox's contains() by mapping our point into the model frame // and testing there. if (modelFrameBox.contains(modelFramePoint)){ @@ -664,7 +630,7 @@ bool Model::convexHullContains(glm::vec3 point) { if (!_calculatedMeshTrianglesValid) { recalculateMeshBoxes(true); } - + // If we are inside the models box, then consider the submeshes... int subMeshIndex = 0; foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { @@ -678,7 +644,7 @@ bool Model::convexHullContains(glm::vec3 point) { insideMesh = false; break; } - + } if (insideMesh) { // It's inside this mesh, return true. @@ -717,7 +683,7 @@ void Model::recalculateMeshPartOffsets() { // Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these // can occur multiple times. In addition, rendering does it's own ray picking in order to decide which // entity-scripts to call. I think it would be best to do the picking once-per-frame (in cpu, or gpu if possible) -// and then the calls use the most recent such result. +// and then the calls use the most recent such result. void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { PROFILE_RANGE(__FUNCTION__); bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; @@ -762,7 +728,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f)); glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f)); glm::vec3 mv3 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f)); - + // track the mesh parts in model space if (!atLeastOnePointInBounds) { thisPartBounds.setBox(mv0, 0.0f); @@ -778,18 +744,18 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { glm::vec3 v1 = calculateScaledOffsetPoint(mv1); glm::vec3 v2 = calculateScaledOffsetPoint(mv2); glm::vec3 v3 = calculateScaledOffsetPoint(mv3); - + // Sam's recommended triangle slices Triangle tri1 = { v0, v1, v3 }; Triangle tri2 = { v1, v2, v3 }; - + // NOTE: Random guy on the internet's recommended triangle slices //Triangle tri1 = { v0, v1, v2 }; //Triangle tri2 = { v2, v3, v0 }; - + thisMeshTriangles.push_back(tri1); thisMeshTriangles.push_back(tri2); - + } } @@ -851,7 +817,7 @@ void Model::renderSetup(RenderArgs* args) { _dilatedTextures.append(dilated); } } - + if (!_meshGroupsKnown && isLoaded()) { segregateMeshGroups(); } @@ -864,7 +830,7 @@ public: transparent(transparent), model(model), url(model->getURL()), meshIndex(meshIndex), partIndex(partIndex) { } typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - + bool transparent; Model* model; QUrl url; @@ -873,14 +839,14 @@ public: }; namespace render { - template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { + template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { if (!payload->model->isVisible()) { return ItemKey::Builder().withInvisible().build(); } return payload->transparent ? ItemKey::Builder::transparentShape() : ItemKey::Builder::opaqueShape(); } - - template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { + + template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { if (payload) { return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } @@ -934,7 +900,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan _renderItems.insert(item, renderPayload); somethingAdded = true; } - + _readyWhenAdded = readyToAddToScene(); return somethingAdded; @@ -966,7 +932,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan _renderItems.insert(item, renderPayload); somethingAdded = true; } - + _readyWhenAdded = readyToAddToScene(); return somethingAdded; @@ -988,7 +954,7 @@ void Model::renderDebugMeshBoxes() { _debugMeshBoxesID = DependencyManager::get()->allocateID(); } QVector points; - + glm::vec3 brn = box.getCorner(); glm::vec3 bln = brn + glm::vec3(box.getDimensions().x, 0, 0); glm::vec3 brf = brn + glm::vec3(0, 0, box.getDimensions().z); @@ -1022,12 +988,12 @@ void Model::renderDebugMeshBoxes() { { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow { 0.0f, 1.0f, 1.0f, 1.0f }, // cyan { 1.0f, 1.0f, 1.0f, 1.0f }, // white - { 0.0f, 0.5f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 0.5f, 1.0f }, - { 0.5f, 0.0f, 0.5f, 1.0f }, - { 0.5f, 0.5f, 0.0f, 1.0f }, + { 0.0f, 0.5f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 0.5f, 1.0f }, + { 0.5f, 0.0f, 0.5f, 1.0f }, + { 0.5f, 0.5f, 0.0f, 1.0f }, { 0.0f, 0.5f, 0.5f, 1.0f } }; - + DependencyManager::get()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]); DependencyManager::get()->renderVertices(gpu::LINES, _debugMeshBoxesID); colorNdx++; @@ -1062,7 +1028,7 @@ Extents Model::getUnscaledMeshExtents() const { if (!isActive()) { return Extents(); } - + const Extents& extents = _geometry->getFBXGeometry().meshExtents; // even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which @@ -1070,7 +1036,7 @@ Extents Model::getUnscaledMeshExtents() const { glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f)); glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f)); Extents scaledExtents = { minimum, maximum }; - + return scaledExtents; } @@ -1079,12 +1045,12 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const { glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f)); glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f)); - Extents scaledOffsetExtents = { ((minimum + _offset) * _scale), + Extents scaledOffsetExtents = { ((minimum + _offset) * _scale), ((maximum + _offset) * _scale) }; Extents rotatedExtents = scaledOffsetExtents.getRotated(_rotation); - Extents translatedExtents = { rotatedExtents.minimum + _translation, + Extents translatedExtents = { rotatedExtents.minimum + _translation, rotatedExtents.maximum + _translation }; return translatedExtents; @@ -1106,39 +1072,27 @@ glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const { bool Model::getJointState(int index, glm::quat& rotation) const { - if (_rig) { - return _rig->getJointState(index, rotation); - } else { - if (index == -1 || index >= _jointStates.size()) { - return false; - } - const JointState& state = _jointStates.at(index); - rotation = state.getRotationInConstrainedFrame(); - return !state.rotationIsDefault(rotation); + if (index == -1 || index >= _jointStates.size()) { + return false; } + const JointState& state = _jointStates.at(index); + rotation = state.getRotationInConstrainedFrame(); + return !state.rotationIsDefault(rotation); } bool Model::getVisibleJointState(int index, glm::quat& rotation) const { - if (_rig) { - return _rig->getVisibleJointState(index, rotation); - } else { - if (index == -1 || index >= _jointStates.size()) { - return false; - } - const JointState& state = _jointStates.at(index); - rotation = state.getVisibleRotationInConstrainedFrame(); - return !state.rotationIsDefault(rotation); + if (index == -1 || index >= _jointStates.size()) { + return false; } + const JointState& state = _jointStates.at(index); + rotation = state.getVisibleRotationInConstrainedFrame(); + return !state.rotationIsDefault(rotation); } void Model::clearJointState(int index) { - if (_rig) { - _rig->clearJointState(index); - } else { - if (index != -1 && index < _jointStates.size()) { - JointState& state = _jointStates[index]; - state.setRotationInConstrainedFrame(glm::quat(), 0.0f); - } + if (index != -1 && index < _jointStates.size()) { + JointState& state = _jointStates[index]; + state.setRotationInConstrainedFrame(glm::quat(), 0.0f); } } @@ -1153,16 +1107,12 @@ void Model::clearJointAnimationPriority(int index) { } void Model::setJointState(int index, bool valid, const glm::quat& rotation, float priority) { - if (_rig) { - _rig->setJointState(index, valid, rotation, priority); - } else { - if (index != -1 && index < _jointStates.size()) { - JointState& state = _jointStates[index]; - if (valid) { - state.setRotationInConstrainedFrame(rotation, priority); - } else { - state.restoreRotation(1.0f, priority); - } + if (index != -1 && index < _jointStates.size()) { + JointState& state = _jointStates[index]; + if (valid) { + state.setRotationInConstrainedFrame(rotation, priority); + } else { + state.restoreRotation(1.0f, priority); } } } @@ -1189,7 +1139,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo onInvalidate(); - // if so instructed, keep the current geometry until the new one is loaded + // if so instructed, keep the current geometry until the new one is loaded _nextGeometry = DependencyManager::get()->getGeometry(url, fallback, delayLoad); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; if (!retainCurrent || !isActive() || (_nextGeometry && _nextGeometry->isLoaded())) { @@ -1199,14 +1149,14 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo void Model::geometryRefreshed() { QObject* sender = QObject::sender(); - + if (sender == _geometry) { _readyWhenAdded = false; // reset out render items. _needsReload = true; invalidCalculatedMeshBoxes(); - + onInvalidate(); - + // if so instructed, keep the current geometry until the new one is loaded _nextGeometry = DependencyManager::get()->getGeometry(_url); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; @@ -1226,7 +1176,7 @@ const QSharedPointer Model::getCollisionGeometry(bool delayLoad if (_collisionGeometry && _collisionGeometry->isLoaded()) { return _collisionGeometry; } - + return QSharedPointer(); } @@ -1238,82 +1188,62 @@ void Model::setCollisionModelURL(const QUrl& url) { _collisionGeometry = DependencyManager::get()->getGeometry(url, QUrl(), true); } - -bool Model::getJointStateAtIndex(int jointIndex, JointState& jointState) const { - if (_rig) { - return _rig->getJointStateAtIndex(jointIndex, jointState); - } else { - if (jointIndex == -1 || jointIndex >= _jointStates.size()) { - return false; - } - jointState = _jointStates[jointIndex]; - return true; - } -} - bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const { - JointState jointState; - if (!getJointStateAtIndex(jointIndex, jointState)) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } // position is in world-frame - position = _translation + _rotation * jointState.getPosition(); + position = _translation + _rotation * _jointStates[jointIndex].getPosition(); return true; } bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { - JointState jointState; - if (!getJointStateAtIndex(jointIndex, jointState)) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } // position is in model-frame - position = extractTranslation(jointState.getTransform()); + position = extractTranslation(_jointStates[jointIndex].getTransform()); return true; } bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const { - JointState jointState; - if (!getJointStateAtIndex(jointIndex, jointState)) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _rotation * jointState.getRotation(); + rotation = _rotation * _jointStates[jointIndex].getRotation(); return true; } bool Model::getJointRotation(int jointIndex, glm::quat& rotation) const { - JointState jointState; - if (!getJointStateAtIndex(jointIndex, jointState)) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = jointState.getRotation(); + rotation = _jointStates[jointIndex].getRotation(); return true; } bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const { - JointState jointState; - if (!getJointStateAtIndex(jointIndex, jointState)) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _rotation * jointState.getRotation(); + rotation = _rotation * _jointStates[jointIndex].getRotation(); return true; } bool Model::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const { - JointState jointState; - if (!getJointStateAtIndex(jointIndex, jointState)) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } // position is in world-frame - position = _translation + _rotation * jointState.getVisiblePosition(); + position = _translation + _rotation * _jointStates[jointIndex].getVisiblePosition(); return true; } bool Model::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const { - JointState jointState; - if (!getJointStateAtIndex(jointIndex, jointState)) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _rotation * jointState.getVisibleRotation(); + rotation = _rotation * _jointStates[jointIndex].getVisibleRotation(); return true; } @@ -1341,11 +1271,11 @@ public: Blender(Model* model, int blendNumber, const QWeakPointer& geometry, const QVector& meshes, const QVector& blendshapeCoefficients); - + virtual void run(); private: - + QPointer _model; int _blendNumber; QWeakPointer _geometry; @@ -1419,10 +1349,10 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension, bool forceRes } return; } - + if (forceRescale || _scaleToFit != scaleToFit || glm::length(_scaleToFitDimensions) != largestDimension) { _scaleToFit = scaleToFit; - + // we only need to do this work if we're "turning on" scale to fit. if (scaleToFit) { Extents modelMeshExtents = getUnscaledMeshExtents(); @@ -1443,7 +1373,7 @@ void Model::scaleToFit() { // we didn't yet have an active mesh. We can only enter this scaleToFit() in this state // if we now do have an active mesh, so we take this opportunity to actually determine // the correct scale. - if (_scaleToFit && _scaleToFitDimensions.y == FAKE_DIMENSION_PLACEHOLDER + if (_scaleToFit && _scaleToFitDimensions.y == FAKE_DIMENSION_PLACEHOLDER && _scaleToFitDimensions.z == FAKE_DIMENSION_PLACEHOLDER) { setScaleToFit(_scaleToFit, _scaleToFitDimensions.x); } @@ -1478,7 +1408,7 @@ 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 @@ -1508,20 +1438,12 @@ void Model::updateClusterMatrices() { if (_showTrueJointTransforms) { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - JointState jointState; - if (!getJointStateAtIndex(cluster.jointIndex, jointState)) { - return; - } - state.clusterMatrices[j] = modelToWorld * jointState.getTransform() * cluster.inverseBindMatrix; + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix; } } else { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - JointState jointState; - if (!getJointStateAtIndex(cluster.jointIndex, jointState)) { - return; - } - state.clusterMatrices[j] = modelToWorld * jointState.getVisibleTransform() * cluster.inverseBindMatrix; + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix; } } } @@ -1529,26 +1451,21 @@ void Model::updateClusterMatrices() { void Model::simulateInternal(float deltaTime) { // update the world space transforms for all joints - + // update animations foreach (const AnimationHandlePointer& handle, _runningAnimations) { handle->simulate(deltaTime); } - if (_rig) { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - _rig->updateJointStates(parentTransform); - _rig->resetAllTransformsChanged(); - } else { - updateJointStates(); - for (int i = 0; i < _jointStates.size(); i++) { - _jointStates[i].resetTransformChanged(); - } + for (int i = 0; i < _jointStates.size(); i++) { + updateJointState(i); + } + for (int i = 0; i < _jointStates.size(); i++) { + _jointStates[i].resetTransformChanged(); } _shapesAreDirty = !_shapes.isEmpty(); - + const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 modelToWorld = glm::mat4_cast(_rotation); for (int i = 0; i < _meshStates.size(); i++) { @@ -1557,24 +1474,16 @@ void Model::simulateInternal(float deltaTime) { if (_showTrueJointTransforms) { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - JointState jointState; - if (!getJointStateAtIndex(cluster.jointIndex, jointState)) { - return; - } - state.clusterMatrices[j] = modelToWorld * jointState.getTransform() * cluster.inverseBindMatrix; + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix; } } else { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - JointState jointState; - if (!getJointStateAtIndex(cluster.jointIndex, jointState)) { - return; - } - state.clusterMatrices[j] = modelToWorld * jointState.getVisibleTransform() * cluster.inverseBindMatrix; + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix; } } } - + // post the blender if we're not currently waiting for one to finish if (geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; @@ -1582,18 +1491,10 @@ void Model::simulateInternal(float deltaTime) { } } -void Model::updateJointStates() { - assert(!_rig); - for (int i = 0; i < _jointStates.size(); i++) { - updateJointState(i); - } -} - void Model::updateJointState(int index) { - assert(!_rig); JointState& state = _jointStates[index]; const FBXJoint& joint = state.getFBXJoint(); - + // compute model transforms int parentIndex = joint.parentIndex; if (parentIndex == -1) { @@ -1614,38 +1515,13 @@ void Model::updateVisibleJointStates() { // no need to update visible transforms return; } - if (_rig) { - _rig->updateVisibleJointStates(); - } else { - for (int i = 0; i < _jointStates.size(); i++) { - _jointStates[i].slaveVisibleTransform(); - } + for (int i = 0; i < _jointStates.size(); i++) { + _jointStates[i].slaveVisibleTransform(); } } -glm::quat Model::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority) { - glm::quat endRotation; - if (jointIndex == -1 || _jointStates.isEmpty()) { - return endRotation; - } - JointState& state = _jointStates[jointIndex]; - state.setRotationInBindFrame(rotation, priority); - endRotation = state.getRotationInBindFrame(); - return endRotation; -} - - bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, - int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) { - if (_rig) { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - bool result = _rig->setJointPosition(jointIndex, position, rotation, useRotation, lastFreeIndex, allIntermediatesFree, - alignment, priority, parentTransform); - _shapesAreDirty = !_shapes.isEmpty(); - return result; - } - + int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } @@ -1730,16 +1606,8 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const gl return true; } -void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, - const glm::quat& targetRotation, float priority) { +void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority) { // NOTE: targetRotation is from bind- to model-frame - if (_rig) { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::mat4 topParentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - _rig->inverseKinematics( endIndex, targetPosition, targetRotation, priority, topParentTransform); - _shapesAreDirty = !_shapes.isEmpty(); - return; - } if (endIndex == -1 || _jointStates.isEmpty()) { return; @@ -1849,20 +1717,17 @@ void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, // set final rotation of the end joint endState.setRotationInBindFrame(targetRotation, priority, true); - + _shapesAreDirty = !_shapes.isEmpty(); } bool Model::restoreJointPosition(int jointIndex, float fraction, float priority) { - if (_rig) { - return _rig->restoreJointPosition(jointIndex, fraction, priority); - } if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& freeLineage = geometry.joints.at(jointIndex).freeLineage; - + foreach (int index, freeLineage) { JointState& state = _jointStates[index]; state.restoreRotation(fraction, priority); @@ -1871,9 +1736,6 @@ bool Model::restoreJointPosition(int jointIndex, float fraction, float priority) } float Model::getLimbLength(int jointIndex) const { - if (_rig) { - return _rig->getLimbLength(jointIndex, _scale); - } if (jointIndex == -1 || _jointStates.isEmpty()) { return 0.0f; } @@ -1907,7 +1769,7 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointergetFBXGeometry(); + const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry(); int index = 0; for (int i = 0; i < fbxGeometry.meshes.size(); i++) { const FBXMesh& mesh = fbxGeometry.meshes.at(i); @@ -1928,7 +1790,7 @@ void Model::setGeometry(const QSharedPointer& newGeometry) { if (_geometry == newGeometry) { return; } - + if (_geometry) { _geometry->disconnect(_geometry.data(), &Resource::onRefresh, this, &Model::geometryRefreshed); } @@ -1941,10 +1803,10 @@ void Model::applyNextGeometry() { deleteGeometry(); _dilatedTextures.clear(); _lodHysteresis = _nextLODHysteresis; - + // we retain a reference to the base geometry so that its reference count doesn't fall to zero setGeometry(_nextGeometry); - + _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes _needsReload = false; // we are loaded now! @@ -1955,12 +1817,9 @@ void Model::applyNextGeometry() { void Model::deleteGeometry() { _blendedVertexBuffers.clear(); _jointStates.clear(); - if (_rig) { - _rig->clearJointStates(); - } _meshStates.clear(); clearShapes(); - + for (QSet::iterator it = _animationHandles.begin(); it != _animationHandles.end(); ) { AnimationHandlePointer handle = it->lock(); if (handle) { @@ -1970,11 +1829,11 @@ void Model::deleteGeometry() { it = _animationHandles.erase(it); } } - + if (_geometry) { _geometry->clearLoadPriority(this); } - + _blendedBlendshapeCoefficients.clear(); } @@ -1988,9 +1847,9 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { return calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents); } } - + if (_geometry->getFBXGeometry().meshes.size() > meshIndex) { - + // FIX ME! - This is currently a hack because for some mesh parts our efforts to calculate the bounding // box of the mesh part fails. It seems to create boxes that are not consistent with where the // geometry actually renders. If instead we make all the parts share the bounds of the entire subMesh @@ -2015,7 +1874,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (!_readyWhenAdded) { return; // bail asap } - + // We need to make sure we have valid offsets calculated before we can render if (!_calculatedMeshPartOffsetValid) { _mutex.lock(); @@ -2040,13 +1899,13 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // guard against partially loaded meshes if (meshIndex >= networkMeshes.size() || meshIndex >= geometry.meshes.size() || meshIndex >= _meshStates.size() ) { - return; + return; } const NetworkMesh& networkMesh = networkMeshes.at(meshIndex); const FBXMesh& mesh = geometry.meshes.at(meshIndex); const MeshState& state = _meshStates.at(meshIndex); - + bool translucentMesh = translucent; // networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); @@ -2076,7 +1935,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran DependencyManager::get()->renderWireCube(batch, 1.0f, cubeColor); } #endif //def DEBUG_BOUNDING_PARTS - + if (wireframe) { translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; } @@ -2091,14 +1950,14 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown // to false to rebuild out mesh groups. - + if (meshIndex < 0 || meshIndex >= networkMeshes.size() || meshIndex > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. _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 return; // FIXME! } - + batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { @@ -2110,7 +1969,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (_transforms.empty()) { _transforms.push_back(Transform()); } - + if (isSkinned) { batch._glUniformMatrix4fv(locations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); @@ -2150,7 +2009,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran qCDebug(renderutils) << "WARNING: material == nullptr!!!"; } #endif - + if (material != nullptr) { // apply material properties @@ -2192,12 +2051,12 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); } - if (!mesh.tangents.isEmpty()) { + if (!mesh.tangents.isEmpty()) { NetworkTexture* normalMap = networkPart.normalTexture.data(); batch.setResourceTexture(1, (!normalMap || !normalMap->isLoaded()) ? textureCache->getBlueTexture() : normalMap->getGPUTexture()); } - + if (locations->specularTextureUnit >= 0) { NetworkTexture* specularMap = networkPart.specularTexture.data(); batch.setResourceTexture(locations->specularTextureUnit, (!specularMap || !specularMap->isLoaded()) ? @@ -2215,18 +2074,18 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran float emissiveOffset = part.emissiveParams.x; float emissiveScale = part.emissiveParams.y; batch._glUniform2f(locations->emissiveParams, emissiveOffset, emissiveScale); - + NetworkTexture* emissiveMap = networkPart.emissiveTexture.data(); batch.setResourceTexture(locations->emissiveTextureUnit, (!emissiveMap || !emissiveMap->isLoaded()) ? textureCache->getGrayTexture() : emissiveMap->getGPUTexture()); } - + if (translucent && locations->lightBufferUnit >= 0) { DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); } } } - + qint64 offset; { // FIXME_STUTTER: We should n't have any lock here @@ -2263,7 +2122,7 @@ void Model::segregateMeshGroups() { qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } - + _transparentRenderItems.clear(); _opaqueRenderItems.clear(); @@ -2272,7 +2131,7 @@ void Model::segregateMeshGroups() { const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); const MeshState& state = _meshStates.at(i); - + bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); @@ -2280,7 +2139,7 @@ void Model::segregateMeshGroups() { bool hasLightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; bool wireframe = isWireframe(); - + if (wireframe) { translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; } @@ -2297,7 +2156,7 @@ void Model::segregateMeshGroups() { } } _meshGroupsKnown = true; -} +} void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, @@ -2317,7 +2176,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram(); locations = (*pipeline).second._locations.get(); - + // Setup the One pipeline batch.setPipeline((*pipeline).second._pipeline); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 5289302390..1b4df6821c 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -64,7 +64,7 @@ public: static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; } - Model(QObject* parent = NULL, RigPointer rig = nullptr); + Model(QObject* parent = nullptr, RigPointer rig = nullptr); virtual ~Model(); /// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension @@ -206,6 +206,7 @@ public: QStringList getJointNames() const; + AnimationHandlePointer createAnimationHandle(); const QList& getRunningAnimations() const { return _runningAnimations; } @@ -259,7 +260,6 @@ protected: bool _showTrueJointTransforms; - bool getJointStateAtIndex(int jointIndex, JointState& jointState) const; QVector _jointStates; class MeshState { @@ -281,13 +281,10 @@ protected: void simulateInternal(float deltaTime); /// Updates the state of the joint at the specified index. - void updateJointStates(); virtual void updateJointState(int index); virtual void updateVisibleJointStates(); - - glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority); - + /// \param jointIndex index of joint in model structure /// \param position position of joint in model-frame /// \param rotation rotation of joint in model-frame @@ -297,8 +294,8 @@ protected: /// \param alignment /// \return true if joint exists bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation = glm::quat(), - bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, - const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); + bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, + const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); /// Restores the indexed joint to its default position. /// \param fraction the fraction of the default position to apply (i.e., 0.25f to slerp one fourth of the way to diff --git a/tools/vhacd-util/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp index f1ff0e9e4f..4e7e413770 100644 --- a/tools/vhacd-util/src/VHACDUtil.cpp +++ b/tools/vhacd-util/src/VHACDUtil.cpp @@ -113,6 +113,8 @@ void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result, int index1 = triangles[i * 3 + 1] + indexStartOffset; int index2 = triangles[i * 3 + 2] + indexStartOffset; + // TODO: skip triangles with a normal that points more negative-y than positive-y + glm::vec3 p0 = result.vertices[index0]; glm::vec3 p1 = result.vertices[index1]; glm::vec3 p2 = result.vertices[index2];