diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 65ab6b8d44..199c05af48 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -292,6 +292,21 @@ static TextRenderer* textRenderer(TextRendererType type) { return displayNameRenderer; } +bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + auto avatarPayload = new render::Payload(self); + auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload); + _renderItemID = scene->allocateID(); + pendingChanges.resetItem(_renderItemID, avatarPayloadPointer); + _skeletonModel.addToScene(scene, pendingChanges); + getHead()->getFaceModel().addToScene(scene, pendingChanges); + return true; +} + +void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + pendingChanges.removeItem(_renderItemID); + _skeletonModel.removeFromScene(scene, pendingChanges); +} + void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) { if (_referential) { _referential->update(); @@ -504,6 +519,20 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { } void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) { + // check to see if when we added our models to the scene they were ready, if they were not ready, then + // fix them up in the scene + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + render::PendingChanges pendingChanges; + if (_skeletonModel.needsFixupInScene()) { + _skeletonModel.removeFromScene(scene, pendingChanges); + _skeletonModel.addToScene(scene, pendingChanges); + } + if (getHead()->getFaceModel().needsFixupInScene()) { + getHead()->getFaceModel().removeFromScene(scene, pendingChanges); + getHead()->getFaceModel().addToScene(scene, pendingChanges); + } + scene->enqueuePendingChanges(pendingChanges); + { Glower glower(renderArgs, glowLevel); @@ -518,7 +547,8 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool if (postLighting) { getHand()->render(renderArgs, false); } else { - _skeletonModel.render(renderArgs, 1.0f); + // NOTE: we no longer call this here, because we've added all the model parts as renderable items in the scene + //_skeletonModel.render(renderArgs, 1.0f); renderAttachments(renderArgs); } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b8f2d3a513..001ff8aa85 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -83,6 +83,12 @@ public: virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting = false); + bool addToScene(AvatarSharedPointer self, std::shared_ptr scene, + render::PendingChanges& pendingChanges); + + void removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, + render::PendingChanges& pendingChanges); + //setters void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); } void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 8f8a3a8ef3..49a8012cd9 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -63,13 +63,8 @@ void AvatarManager::init() { _avatarHash.insert(MY_AVATAR_KEY, _myAvatar); render::ScenePointer scene = Application::getInstance()->getMain3DScene(); - auto avatarPayload = new render::Payload(_myAvatar); - auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload); - static_cast(_myAvatar.get())->_renderItemID = scene->allocateID(); - render::PendingChanges pendingChanges; - pendingChanges.resetItem(static_cast(_myAvatar.get())->_renderItemID, avatarPayloadPointer); - + _myAvatar->addToScene(_myAvatar, scene, pendingChanges); scene->enqueuePendingChanges(pendingChanges); } @@ -145,18 +140,11 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() { // virtual AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) { - AvatarSharedPointer avatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer); - + std::shared_ptr avatar = std::dynamic_pointer_cast(AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer)); render::ScenePointer scene = Application::getInstance()->getMain3DScene(); - auto avatarPayload = new render::Payload(avatar); - auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload); - static_cast(avatar.get())->_renderItemID = scene->allocateID(); - render::PendingChanges pendingChanges; - pendingChanges.resetItem(static_cast(avatar.get())->_renderItemID, avatarPayloadPointer); - + avatar->addToScene(avatar, scene, pendingChanges); scene->enqueuePendingChanges(pendingChanges); - return avatar; } @@ -177,17 +165,15 @@ void AvatarManager::removeAvatarMotionState(Avatar* avatar) { void AvatarManager::removeAvatar(const QUuid& sessionUUID) { AvatarHash::iterator avatarIterator = _avatarHash.find(sessionUUID); if (avatarIterator != _avatarHash.end()) { - Avatar* avatar = reinterpret_cast(avatarIterator.value().get()); - if (avatar != _myAvatar.get() && avatar->isInitialized()) { - removeAvatarMotionState(avatar); - + std::shared_ptr avatar = std::dynamic_pointer_cast(avatarIterator.value()); + if (avatar != _myAvatar && avatar->isInitialized()) { + removeAvatarMotionState(avatar.get()); _avatarFades.push_back(avatarIterator.value()); _avatarHash.erase(avatarIterator); } - render::ScenePointer scene = Application::getInstance()->getMain3DScene(); render::PendingChanges pendingChanges; - pendingChanges.removeItem(avatar->_renderItemID); + avatar->removeFromScene(avatar, scene, pendingChanges); scene->enqueuePendingChanges(pendingChanges); } } diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 524ec23aff..cb35497960 100644 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -40,17 +40,6 @@ class Hand : public HandData { public: Hand(Avatar* owningAvatar); - struct HandBall - { - glm::vec3 position; // the actual dynamic position of the ball at any given time - glm::quat rotation; // the rotation of the ball - glm::vec3 velocity; // the velocity of the ball - float radius; // the radius of the ball - bool isCollidable; // whether or not the ball responds to collisions - bool isColliding; // ball is currently colliding - float touchForce; // a scalar determining the amount that the cursor (or hand) is penetrating the ball - }; - void simulate(float deltaTime, bool isMine); void render(RenderArgs* renderArgs, bool isMine); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index d2af14f696..c4bf5e65fc 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -298,7 +298,8 @@ void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustu renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); } } else { - _faceModel.render(renderArgs, alpha); + // NOTE: we don't need to call this here because the model has been added as payload items + //_faceModel.render(renderArgs, alpha); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 249f8166ac..8407824750 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1171,10 +1171,25 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g } void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) { + if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { return; // wait until both models are loaded } + // check to see if when we added our models to the scene they were ready, if they were not ready, then + // fix them up in the scene + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + render::PendingChanges pendingChanges; + if (_skeletonModel.needsFixupInScene()) { + _skeletonModel.removeFromScene(scene, pendingChanges); + _skeletonModel.addToScene(scene, pendingChanges); + } + if (getHead()->getFaceModel().needsFixupInScene()) { + getHead()->getFaceModel().removeFromScene(scene, pendingChanges); + getHead()->getFaceModel().addToScene(scene, pendingChanges); + } + scene->enqueuePendingChanges(pendingChanges); + Camera *camera = Application::getInstance()->getCamera(); const glm::vec3 cameraPos = camera->getPosition(); @@ -1195,7 +1210,9 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo // Render the body's voxels and head if (!postLighting) { - _skeletonModel.render(renderArgs, 1.0f); + + // NOTE: we no longer call this here, because we've added all the model parts as renderable items in the scene + //_skeletonModel.render(renderArgs, 1.0f); renderAttachments(renderArgs); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e2f4ca51a0..2aa08d36f3 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -255,9 +255,12 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { } void SkeletonModel::updateJointState(int index) { + if (index > _jointStates.size()) { + return; // bail + } JointState& state = _jointStates[index]; const FBXJoint& joint = state.getFBXJoint(); - if (joint.parentIndex != -1) { + if (joint.parentIndex != -1 && joint.parentIndex <= _jointStates.size()) { const JointState& parentState = _jointStates.at(joint.parentIndex); const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (index == geometry.leanJointIndex) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 43f340119b..cc6693133f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -501,7 +501,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { _viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum(); // Setup batch transform matrices - gpu::Batch batch; + gpu::Batch batch; // FIX ME - this is very suspicious! glm::mat4 projMat; Transform viewMat; frustum->evalProjectionMatrix(projMat); @@ -509,7 +509,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderArgs->_batch = &batch; + renderArgs->_batch = &batch; // FIX ME - this is very suspicious! _tree->lockForRead(); @@ -525,6 +525,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { Model::endScene(renderArgs); _tree->unlock(); + // FIX ME - this is very suspicious! // glPushMatrix(); // renderArgs->_context->render(batch); // glPopMatrix(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 54f0fbd540..312890a188 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -406,6 +406,7 @@ void Model::reset() { } _meshGroupsKnown = false; + _readyWhenAdded = false; // in case any of our users are using scenes } bool Model::updateGeometry() { @@ -456,6 +457,7 @@ bool Model::updateGeometry() { _dilatedTextures.clear(); _geometry = geometry; _meshGroupsKnown = false; + _readyWhenAdded = false; // in case any of our users are using scenes initJointStates(newJointStates); needToRebuild = true; } else if (_jointStates.isEmpty()) { @@ -704,10 +706,26 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { int i2 = part.quadIndices[vIndex++]; int i3 = part.quadIndices[vIndex++]; - glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f))); - glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f))); - glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); - glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f))); + glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f)); + 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); + atLeastOnePointInBounds = true; + } else { + thisPartBounds += mv0; + } + thisPartBounds += mv1; + thisPartBounds += mv2; + thisPartBounds += mv3; + + glm::vec3 v0 = calculateScaledOffsetPoint(mv0); + 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 }; @@ -720,14 +738,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { thisMeshTriangles.push_back(tri1); thisMeshTriangles.push_back(tri2); - if (!atLeastOnePointInBounds) { - thisPartBounds.setBox(v0, 0.0f); - atLeastOnePointInBounds = true; - } - thisPartBounds += v0; - thisPartBounds += v1; - thisPartBounds += v2; - thisPartBounds += v3; } } @@ -739,21 +749,27 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { int i1 = part.triangleIndices[vIndex++]; int i2 = part.triangleIndices[vIndex++]; - glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f))); - glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f))); - glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); + glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f)); + 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)); + + // track the mesh parts in model space + if (!atLeastOnePointInBounds) { + thisPartBounds.setBox(mv0, 0.0f); + atLeastOnePointInBounds = true; + } else { + thisPartBounds += mv0; + } + thisPartBounds += mv1; + thisPartBounds += mv2; + + glm::vec3 v0 = calculateScaledOffsetPoint(mv0); + glm::vec3 v1 = calculateScaledOffsetPoint(mv1); + glm::vec3 v2 = calculateScaledOffsetPoint(mv2); Triangle tri = { v0, v1, v2 }; thisMeshTriangles.push_back(tri); - - if (!atLeastOnePointInBounds) { - thisPartBounds.setBox(v0, 0.0f); - atLeastOnePointInBounds = true; - } - thisPartBounds += v0; - thisPartBounds += v1; - thisPartBounds += v2; } } _calculatedMeshPartBoxes[QPair(i, j)] = thisPartBounds; @@ -819,7 +835,6 @@ namespace render { template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { if (args) { args->_elementsTouched++; - //qDebug() << "would be TransparentMeshPart: " << payload->meshIndex << "," << payload->partIndex; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); } } @@ -843,7 +858,9 @@ namespace render { template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { if (payload) { - return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + Item::Bound result = payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + //qDebug() << "payloadGetBound(OpaqueMeshPart) " << result; + return result; } return render::Item::Bound(); } @@ -857,6 +874,10 @@ namespace render { bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { + if (!_meshGroupsKnown && isLoadedWithTextures()) { + segregateMeshGroups(); + } + bool somethingAdded = false; qDebug() << "Model::addToScene : " << this->getURL().toString(); @@ -883,6 +904,8 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan _renderItems << item; somethingAdded = true; } + + _readyWhenAdded = readyToAddToScene(); return somethingAdded; } @@ -897,9 +920,8 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin pendingChanges.removeItem(item); } _renderItems.clear(); - + _readyWhenAdded = false; qDebug() << "Model::removeFromScene : " << this->getURL().toString(); - } bool Model::render(RenderArgs* renderArgs, float alpha) { @@ -1219,6 +1241,11 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const { return translatedExtents; } +/// Returns the world space equivalent of some box in model space. +AABox Model::calculateScaledOffsetAABox(const AABox& box) const { + return AABox(calculateScaledOffsetExtents(Extents(box))); +} + glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const { // we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix glm::vec3 offsetPoint = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(point, 1.0f)); @@ -1539,6 +1566,12 @@ void Model::snapToRegistrationPoint() { } void Model::simulate(float deltaTime, bool fullUpdate) { + /* + qDebug() << "Model::simulate()"; + qDebug() << " _translation:" << _translation; + qDebug() << " _rotation:" << _rotation; + */ + fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); @@ -1929,6 +1962,7 @@ void Model::applyNextGeometry() { _baseGeometry = _nextBaseGeometry; _geometry = _nextGeometry; _meshGroupsKnown = false; + _readyWhenAdded = false; // in case any of our users are using scenes _nextBaseGeometry.reset(); _nextGeometry.reset(); } @@ -2216,23 +2250,15 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { recalculateMeshBoxes(true); } if (_calculatedMeshPartBoxesValid && _calculatedMeshPartBoxes.contains(QPair(meshIndex, partIndex))) { - return _calculatedMeshPartBoxes[QPair(meshIndex, partIndex)]; - } - if (!_calculatedMeshBoxesValid) { - return _calculatedMeshBoxes[meshIndex]; + return calculateScaledOffsetAABox(_calculatedMeshPartBoxes[QPair(meshIndex, partIndex)]); } return AABox(); } void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { - renderSetup(args); - - /* - if (translucent) { - renderCore(args, 1.0f); - return; + if (!_readyWhenAdded) { + return; // bail asap } - */ auto textureCache = DependencyManager::get(); gpu::Batch& batch = *(args->_batch); @@ -2243,13 +2269,13 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran _transforms.push_back(Transform()); } - // _transforms[0] = _viewState->getViewTransform(); - // args->_viewFrustum->evalViewTransform(_transforms[0]); + // _transforms[0] = _viewState->getViewTransform(); + // args->_viewFrustum->evalViewTransform(_transforms[0]); // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) - // _transforms[0].setTranslation(_translation); + // _transforms[0].setTranslation(_translation); - // batch.setViewTransform(_transforms[0]); + // batch.setViewTransform(_transforms[0]); // const float OPAQUE_ALPHA_THRESHOLD = 0.5f; @@ -2259,10 +2285,15 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); + // guard against partially loaded meshes + if (meshIndex >= networkMeshes.size() || meshIndex >= geometry.meshes.size() || meshIndex >= _meshStates.size() ) { + 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(); @@ -2287,6 +2318,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran 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 return; // FIXME! } @@ -2328,6 +2360,11 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran qint64 offset = 0; + // guard against partially loaded meshes + if (partIndex >= networkMesh.parts.size() || partIndex >= mesh.parts.size()) { + return; + } + const NetworkMeshPart& networkPart = networkMesh.parts.at(partIndex); const FBXMeshPart& part = mesh.parts.at(partIndex); model::MaterialPointer material = part._material; @@ -2352,8 +2389,13 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran Texture* diffuseMap = networkPart.diffuseTexture.data(); if (mesh.isEye && diffuseMap) { - diffuseMap = (_dilatedTextures[meshIndex][partIndex] = - static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); + // FIXME - guard against out of bounds here + if (meshIndex < _dilatedTextures.size()) { + if (partIndex < _dilatedTextures[meshIndex].size()) { + diffuseMap = (_dilatedTextures[meshIndex][partIndex] = + static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); + } + } } static bool showDiffuse = true; if (showDiffuse && diffuseMap) { @@ -2623,6 +2665,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. + _readyWhenAdded = false; // in case any of our users are using scenes continue; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 7b44dbee04..dcbdddcb0a 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -123,6 +123,7 @@ public: static void endScene(RenderArgs* args); // new Scene/Engine rendering support + bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return isRenderable() && isActive() && isLoadedWithTextures(); } bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); @@ -157,6 +158,9 @@ public: /// Returns the scaled equivalent of some extents in model space. Extents calculateScaledOffsetExtents(const Extents& extents) const; + /// Returns the world space equivalent of some box in model space. + AABox calculateScaledOffsetAABox(const AABox& box) const; + /// Returns the scaled equivalent of a point in model space. glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const; @@ -542,6 +546,7 @@ private: QSet> _transparentRenderItems; QSet> _opaqueRenderItems; QSet _renderItems; + bool _readyWhenAdded = false; }; Q_DECLARE_METATYPE(QPointer) diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index 3c6be43850..37fba37adc 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -42,12 +42,6 @@ glm::vec3 AABox::calcCenter() const { return center; } -glm::vec3 AABox::calcTopFarLeft() const { - glm::vec3 topFarLeft(_corner); - topFarLeft += _scale; - return topFarLeft; -}; - void AABox::scale(float scale) { _corner = _corner * scale; _scale = _scale * scale; diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index 9beb0a85f2..f185122534 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -47,7 +47,11 @@ public: float getLargestDimension() const { return glm::max(_scale.x, glm::max(_scale.y, _scale.z)); } glm::vec3 calcCenter() const; - glm::vec3 calcTopFarLeft() const; + glm::vec3 calcTopFarLeft() const { return _corner + _scale; } + + const glm::vec3& getMinimum() const { return _corner; } + glm::vec3 getMaximum() const { return _corner + _scale; } + glm::vec3 getVertex(BoxVertex vertex) const; const glm::vec3& getMinimumPoint() const { return _corner; } diff --git a/libraries/shared/src/Extents.h b/libraries/shared/src/Extents.h index 489d48b1c1..647f33699a 100644 --- a/libraries/shared/src/Extents.h +++ b/libraries/shared/src/Extents.h @@ -23,6 +23,10 @@ class AABox; class Extents { public: + Extents(const glm::vec3& minimum, const glm::vec3& maximum) : minimum(minimum), maximum(maximum) { } + Extents() { reset(); } + Extents(const AABox& box) { reset(); add(box); } + /// set minimum and maximum to FLT_MAX and -FLT_MAX respectively void reset(); @@ -58,7 +62,7 @@ public: /// \return new Extents which is original rotated around orign by rotation Extents getRotated(const glm::quat& rotation) const { - Extents temp = { minimum, maximum }; + Extents temp(minimum, maximum); temp.rotate(rotation); return temp; }