diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/logic/executor.cpp | 2 | ||||
-rw-r--r-- | src/plugins/sceneparsers/assimp/assimpimporter.cpp | 47 | ||||
-rw-r--r-- | src/plugins/sceneparsers/assimp/assimpimporter.h | 1 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 5 | ||||
-rw-r--r-- | src/render/geometry/buffer.cpp | 23 | ||||
-rw-r--r-- | src/render/geometry/buffer_p.h | 1 | ||||
-rw-r--r-- | src/render/graphicshelpers/graphicscontext.cpp | 50 |
7 files changed, 95 insertions, 34 deletions
diff --git a/src/logic/executor.cpp b/src/logic/executor.cpp index ab4ac154d..6134e801e 100644 --- a/src/logic/executor.cpp +++ b/src/logic/executor.cpp @@ -96,7 +96,7 @@ void Executor::processLogicFrameUpdates(float dt) const QVector<QNode *> nodes = m_scene->lookupNodes(m_nodeIds); for (QNode *node : nodes) { QFrameAction *frameAction = qobject_cast<QFrameAction *>(node); - if (frameAction) + if (frameAction && frameAction->isEnabled()) frameAction->onTriggered(dt); } diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.cpp b/src/plugins/sceneparsers/assimp/assimpimporter.cpp index 565c61234..d5fc113e3 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.cpp +++ b/src/plugins/sceneparsers/assimp/assimpimporter.cpp @@ -142,7 +142,7 @@ QMatrix4x4 aiMatrix4x4ToQMatrix4x4(const aiMatrix4x4 &matrix) Q_DECL_NOTHROW /*! * Returns a QString from \a str; */ -static inline QString aiStringToQString(const aiString &str) +inline QString aiStringToQString(const aiString &str) { return QString::fromUtf8(str.data, int(str.length)); } @@ -246,6 +246,21 @@ QAttribute *createAttribute(QBuffer *buffer, return attribute; } +QTextureWrapMode::WrapMode wrapModeFromaiTextureMapMode(int mode) +{ + switch (mode) { + case aiTextureMapMode_Wrap: + return QTextureWrapMode::Repeat; + case aiTextureMapMode_Mirror: + return QTextureWrapMode::MirroredRepeat; + case aiTextureMapMode_Decal: + return QTextureWrapMode::ClampToBorder; + case aiTextureMapMode_Clamp: + default: + return QTextureWrapMode::ClampToEdge; + } +} + } // anonymous QStringList AssimpImporter::assimpSupportedFormatsList = AssimpImporter::assimpSupportedFormats(); @@ -1237,18 +1252,28 @@ void AssimpImporter::copyMaterialTextures(QMaterial *material, aiMaterial *assim for (unsigned int i = 0; i < sizeof(textureType)/sizeof(textureType[0]); i++) { aiString path; if (assimpMaterial->GetTexture(textureType[i], 0, &path) == AI_SUCCESS) { - QString fullPath = m_sceneDir.absoluteFilePath(texturePath(path)); + const QString fullPath = m_sceneDir.absoluteFilePath(texturePath(path)); // Load texture if not already loaded - if (!m_scene->m_materialTextures.contains(fullPath)) { - QAbstractTexture *tex = QAbstractNodeFactory::createNode<QTexture2D>("QTexture2D"); - QTextureImage *texImage = QAbstractNodeFactory::createNode<QTextureImage>("QTextureImage"); - texImage->setSource(QUrl::fromLocalFile(fullPath)); - tex->addTextureImage(texImage); - m_scene->m_materialTextures.insert(fullPath, tex); - qCDebug(AssimpImporterLog) << Q_FUNC_INFO << " Loaded Texture " << fullPath; - } + QAbstractTexture *tex = QAbstractNodeFactory::createNode<QTexture2D>("QTexture2D"); + QTextureImage *texImage = QAbstractNodeFactory::createNode<QTextureImage>("QTextureImage"); + texImage->setSource(QUrl::fromLocalFile(fullPath)); + tex->addTextureImage(texImage); + + // Set proper wrapping mode + QTextureWrapMode wrapMode(QTextureWrapMode::Repeat); + int xMode = 0; + int yMode = 0; + + if (assimpMaterial->Get(AI_MATKEY_MAPPINGMODE_U(textureType[i], 0), xMode) == aiReturn_SUCCESS) + wrapMode.setX(wrapModeFromaiTextureMapMode(xMode)); + if (assimpMaterial->Get(AI_MATKEY_MAPPINGMODE_V(textureType[i], 0), yMode) == aiReturn_SUCCESS) + wrapMode.setY(wrapModeFromaiTextureMapMode(yMode)); + + tex->setWrapMode(wrapMode); + + qCDebug(AssimpImporterLog) << Q_FUNC_INFO << " Loaded Texture " << fullPath; setParameterValue(m_scene->m_textureToParameterName[textureType[i]], - material, QVariant::fromValue(m_scene->m_materialTextures[fullPath])); + material, QVariant::fromValue(tex)); } } } diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.h b/src/plugins/sceneparsers/assimp/assimpimporter.h index 7335830f5..e37950981 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.h +++ b/src/plugins/sceneparsers/assimp/assimpimporter.h @@ -143,7 +143,6 @@ private: QMap<uint, QMaterial*> m_materials; QMap<uint, QEffect *> m_effects; QMap<uint, QAbstractTexture *> m_embeddedTextures; - QMap<QString, QAbstractTexture *> m_materialTextures; QMap<aiNode*, Qt3DCore::QEntity*> m_cameras; QHash<aiTextureType, QString> m_textureToParameterName; QVector<Qt3DAnimation::QKeyframeAnimation *> m_animations; diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 4080a72eb..bd8687d5e 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -1013,12 +1013,11 @@ void Renderer::updateGLResources() const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers); for (HBuffer handle: dirtyBufferHandles) { Buffer *buffer = m_nodesManager->bufferManager()->data(handle); - // Perform data upload // Forces creation if it doesn't exit if (!m_graphicsContext->hasGLBufferForBuffer(buffer)) m_graphicsContext->glBufferForRenderBuffer(buffer); - else if (buffer->isDirty()) // Otherwise update the glBuffer - m_graphicsContext->updateBuffer(buffer); + // Update the glBuffer data + m_graphicsContext->updateBuffer(buffer); buffer->unsetDirty(); } } diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp index 44d84f75a..55c86910f 100644 --- a/src/render/geometry/buffer.cpp +++ b/src/render/geometry/buffer.cpp @@ -88,6 +88,9 @@ void Buffer::executeFunctor() { Q_ASSERT(m_functor); m_data = (*m_functor)(); + // Request data to be loaded + forceDataUpload(); + if (m_syncData) { // Send data back to the frontend auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); @@ -101,6 +104,8 @@ void Buffer::executeFunctor() //Called from th sendBufferJob void Buffer::updateDataFromGPUToCPU(QByteArray data) { + // Note: when this is called, data is what's currently in GPU memory + // so m_data shouldn't be reuploaded m_data = data; // Send data back to the frontend auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); @@ -121,12 +126,25 @@ void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang m_access = data.access; m_bufferDirty = true; + if (!m_data.isEmpty()) + forceDataUpload(); + m_functor = data.functor; Q_ASSERT(m_manager); if (m_functor) m_manager->addDirtyBuffer(peerId()); } +void Buffer::forceDataUpload() +{ + // We push back an update with offset = -1 + // As this is the way to force data to be loaded + QBufferUpdate updateNewData; + updateNewData.offset = -1; + m_bufferUpdates.clear(); //previous updates are pointless + m_bufferUpdates.push_back(updateNewData); +} + void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { if (e->type() == PropertyUpdated) { @@ -134,8 +152,11 @@ void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QByteArray propertyName = propertyChange->propertyName(); if (propertyName == QByteArrayLiteral("data")) { QByteArray newData = propertyChange->value().toByteArray(); - m_bufferDirty |= m_data != newData; + bool dirty = m_data != newData; + m_bufferDirty |= dirty; m_data = newData; + if (dirty) + forceDataUpload(); } else if (propertyName == QByteArrayLiteral("updateData")) { Qt3DRender::QBufferUpdate updateData = propertyChange->value().value<Qt3DRender::QBufferUpdate>(); m_bufferUpdates.push_back(updateData); diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h index 9d9606eb0..691d6cc60 100644 --- a/src/render/geometry/buffer_p.h +++ b/src/render/geometry/buffer_p.h @@ -90,6 +90,7 @@ public: private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; + void forceDataUpload(); QBuffer::BufferType m_type; QBuffer::UsageType m_usage; diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 6fa081552..80e8267da 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -1320,16 +1320,16 @@ void GraphicsContext::applyUniform(const ShaderUniform &description, const Unifo break; case UniformType::UInt: - applyUniformHelper<UniformType::Int>(description.m_location, description.m_size, v); + applyUniformHelper<UniformType::UInt>(description.m_location, description.m_size, v); break; case UniformType::UIVec2: - applyUniformHelper<UniformType::IVec2>(description.m_location, description.m_size, v); + applyUniformHelper<UniformType::UIVec2>(description.m_location, description.m_size, v); break; case UniformType::UIVec3: - applyUniformHelper<UniformType::IVec3>(description.m_location, description.m_size, v); + applyUniformHelper<UniformType::UIVec3>(description.m_location, description.m_size, v); break; case UniformType::UIVec4: - applyUniformHelper<UniformType::IVec4>(description.m_location, description.m_size, v); + applyUniformHelper<UniformType::UIVec4>(description.m_location, description.m_size, v); break; case UniformType::Bool: @@ -1501,8 +1501,6 @@ HGLBuffer GraphicsContext::createGLBufferFor(Buffer *buffer) if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type()))) qCWarning(Render::Io) << Q_FUNC_INFO << "buffer binding failed"; - // TO DO: Handle usage pattern - b->allocate(this, buffer->data().constData(), buffer->data().size(), false); return m_renderer->nodeManagers()->glBufferManager()->lookupHandle(buffer->peerId()); } @@ -1528,21 +1526,39 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel // * setData was called changing the whole data or functor (or the usage pattern) // * partial buffer updates where received - // Note: we assume the case where both setData/functor and updates are called to be a misuse - // with unexpected behavior - const QVector<Qt3DRender::QBufferUpdate> updates = std::move(buffer->pendingBufferUpdates()); - if (!updates.empty()) { - for (const Qt3DRender::QBufferUpdate &update : updates) { + // TO DO: Handle usage pattern + QVector<Qt3DRender::QBufferUpdate> updates = std::move(buffer->pendingBufferUpdates()); + for (auto it = updates.begin(); it != updates.end(); ++it) { + auto update = it; + // We have a partial update + if (update->offset >= 0) { + //accumulate sequential updates as single one + int bufferSize = update->data.size(); + auto it2 = it + 1; + while ((it2 != updates.end()) + && (it2->offset - update->offset == bufferSize)) { + bufferSize += it2->data.size(); + ++it2; + } + update->data.resize(bufferSize); + while (it + 1 != it2) { + ++it; + update->data.replace(it->offset - update->offset, it->data.size(), it->data); + it->data.clear(); + } // TO DO: based on the number of updates .., it might make sense to // sometime use glMapBuffer rather than glBufferSubData - b->update(this, update.data.constData(), update.data.size(), update.offset); + b->update(this, update->data.constData(), update->data.size(), update->offset); + } else { + // We have an update that was done by calling QBuffer::setData + // which is used to resize or entirely clear the buffer + // Note: we use the buffer data directly in that case + const int bufferSize = buffer->data().size(); + b->allocate(this, bufferSize, false); // orphan the buffer + b->allocate(this, buffer->data().constData(), bufferSize, false); } - } else { - const int bufferSize = buffer->data().size(); - // TO DO: Handle usage pattern - b->allocate(this, bufferSize, false); // orphan the buffer - b->allocate(this, buffer->data().constData(), bufferSize, false); } + if (releaseBuffer) { b->release(this); if (bufferTypeToGLBufferType(buffer->type()) == GLBuffer::ArrayBuffer) |