From 70c5f64caa7a074e65d2ceb1bec7fb671d8ce804 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 18 Jan 2017 21:55:47 +0100 Subject: [PATCH 1/4] Fix mLocals not being updated in InterpreterContext::updatePtr --- apps/openmw/mwscript/interpretercontext.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 79f856398..b55287cac 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -576,6 +576,9 @@ namespace MWScript void InterpreterContext::updatePtr(const MWWorld::Ptr& base, const MWWorld::Ptr& updated) { if (!mReference.isEmpty() && base == mReference) + { mReference = updated; + mLocals = &mReference.getRefData().getLocals(); + } } } From 45fb4f04b174ee29aa48a5f3f7f5c2327bf431a8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 18 Jan 2017 21:57:50 +0100 Subject: [PATCH 2/4] Update reference of the interpreter context when an Activate results in a take action (Fixes #3727) --- apps/openmw/mwscript/interpretercontext.cpp | 4 ++++ apps/openmw/mwworld/action.cpp | 5 +++++ apps/openmw/mwworld/action.hpp | 4 +++- apps/openmw/mwworld/actiontake.cpp | 3 ++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index b55287cac..210b29639 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -480,6 +480,10 @@ namespace MWScript { boost::shared_ptr action = (ptr.getClass().activate(ptr, actor)); action->execute (actor); + if (action->getTarget() != MWWorld::Ptr() && action->getTarget() != ptr) + { + updatePtr(ptr, action->getTarget()); + } } float InterpreterContext::getSecondsPassed() const diff --git a/apps/openmw/mwworld/action.cpp b/apps/openmw/mwworld/action.cpp index c29377ecb..5663ba38f 100644 --- a/apps/openmw/mwworld/action.cpp +++ b/apps/openmw/mwworld/action.cpp @@ -12,6 +12,11 @@ const MWWorld::Ptr& MWWorld::Action::getTarget() const return mTarget; } +void MWWorld::Action::setTarget(const MWWorld::Ptr& target) +{ + mTarget = target; +} + MWWorld::Action::Action (bool keepSound, const Ptr& target) : mKeepSound (keepSound), mSoundOffset(0), mTarget (target) {} diff --git a/apps/openmw/mwworld/action.hpp b/apps/openmw/mwworld/action.hpp index 38907cf44..6b4dff6aa 100644 --- a/apps/openmw/mwworld/action.hpp +++ b/apps/openmw/mwworld/action.hpp @@ -23,10 +23,12 @@ namespace MWWorld protected: - const Ptr& getTarget() const; + void setTarget(const Ptr&); public: + const Ptr& getTarget() const; + Action (bool keepSound = false, const Ptr& target = Ptr()); ///< \param keepSound Keep playing the sound even if the object the sound is played on is removed. diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index 4e6135764..d858859a6 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -16,7 +16,8 @@ namespace MWWorld { MWBase::Environment::get().getMechanicsManager()->itemTaken( actor, getTarget(), MWWorld::Ptr(), getTarget().getRefData().getCount()); - actor.getClass().getContainerStore (actor).add (getTarget(), getTarget().getRefData().getCount(), actor); + MWWorld::Ptr newitem = *actor.getClass().getContainerStore (actor).add (getTarget(), getTarget().getRefData().getCount(), actor); MWBase::Environment::get().getWorld()->deleteObject (getTarget()); + setTarget(newitem); } } From cc19b4bd8a6ca292300f087ed23138115f89abe9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 19 Jan 2017 02:19:44 +0100 Subject: [PATCH 3/4] Fix door rotation order in collision case (Bug #3707) --- apps/openmw/mwworld/worldimp.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c0dd40a97..2d1e2b139 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1477,8 +1477,6 @@ namespace MWWorld float diff = duration * osg::DegreesToRadians(90.f); float targetRot = std::min(std::max(minRot, oldRot + diff * (it->second == 1 ? 1 : -1)), maxRot); rotateObject(it->first, objPos.rot[0], objPos.rot[1], targetRot); - // the rotation order we want to use - mWorldScene->updateObjectRotation(it->first, false); bool reached = (targetRot == maxRot && it->second) || targetRot == minRot; @@ -1502,6 +1500,9 @@ namespace MWWorld } } + // the rotation order we want to use + mWorldScene->updateObjectRotation(it->first, false); + if (reached) { // Mark as non-moving From ac61535d2ca65e3ddfba3954da472e63e69bac49 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 19 Jan 2017 03:17:49 +0100 Subject: [PATCH 4/4] optimize OSGVertexBuffer by double buffering the vertex array instead of recreating it on every modification --- .../myguiplatform/myguirendermanager.cpp | 95 +++++++++---------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/components/myguiplatform/myguirendermanager.cpp b/components/myguiplatform/myguirendermanager.cpp index 9d1f7100f..5ab7ab736 100644 --- a/components/myguiplatform/myguirendermanager.cpp +++ b/components/myguiplatform/myguirendermanager.cpp @@ -210,7 +210,7 @@ public: osg::ref_ptr mVertexBuffer; // need to hold on to this too as the mVertexBuffer does not hold a ref to its own array - osg::ref_ptr mArray; + osg::ref_ptr mArray; // optional osg::ref_ptr mStateSet; @@ -244,21 +244,25 @@ private: class OSGVertexBuffer : public MyGUI::IVertexBuffer { - osg::ref_ptr mBuffer; - osg::ref_ptr mVertexArray; + osg::ref_ptr mBuffer[2]; + osg::ref_ptr mVertexArray[2]; size_t mNeedVertexCount; - bool mQueuedForDrawing; + unsigned int mCurrentBuffer; + bool mUsed; // has the mCurrentBuffer been submitted to the rendering thread void destroy(); - void create(); + osg::UByteArray* create(); public: OSGVertexBuffer(); - virtual ~OSGVertexBuffer(); + virtual ~OSGVertexBuffer() {} - void markAsQueuedForDrawing(); + void markUsed(); + + osg::Array* getVertexArray(); + osg::VertexBufferObject* getVertexBuffer(); virtual void setVertexCount(size_t count); virtual size_t getVertexCount(); @@ -266,26 +270,18 @@ public: virtual MyGUI::Vertex *lock(); virtual void unlock(); -/*internal:*/ - - osg::VertexBufferObject *getBuffer() const { return mBuffer.get(); } - osg::UByteArray *getArray() const { return mVertexArray.get(); } }; OSGVertexBuffer::OSGVertexBuffer() : mNeedVertexCount(0) - , mQueuedForDrawing(false) -{ -} - -OSGVertexBuffer::~OSGVertexBuffer() + , mCurrentBuffer(0) + , mUsed(false) { - destroy(); } -void OSGVertexBuffer::markAsQueuedForDrawing() +void OSGVertexBuffer::markUsed() { - mQueuedForDrawing = true; + mUsed = true; } void OSGVertexBuffer::setVertexCount(size_t count) @@ -303,48 +299,51 @@ size_t OSGVertexBuffer::getVertexCount() MyGUI::Vertex *OSGVertexBuffer::lock() { - if (mQueuedForDrawing || !mVertexArray) + if (mUsed) { - // Force recreating the buffer, to make sure we are not modifying a buffer currently - // queued for rendering in the last frame's draw thread. - // a more efficient solution might be double buffering - destroy(); - create(); - mQueuedForDrawing = false; + mCurrentBuffer = (mCurrentBuffer+1)%2; + mUsed = false; } - else + osg::UByteArray* array = mVertexArray[mCurrentBuffer]; + if (!array) { - mVertexArray->resize(mNeedVertexCount * sizeof(MyGUI::Vertex)); + array = create(); + } + else if (array->size() != mNeedVertexCount * sizeof(MyGUI::Vertex)) + { + array->resize(mNeedVertexCount * sizeof(MyGUI::Vertex)); } - MYGUI_PLATFORM_ASSERT(mBuffer.valid(), "Vertex buffer is not created"); - - return (MyGUI::Vertex*)&(*mVertexArray)[0]; + return (MyGUI::Vertex*)&(*array)[0]; } void OSGVertexBuffer::unlock() { - mVertexArray->dirty(); - mBuffer->dirty(); + mVertexArray[mCurrentBuffer]->dirty(); + mBuffer[mCurrentBuffer]->dirty(); } -void OSGVertexBuffer::destroy() +osg::UByteArray* OSGVertexBuffer::create() { - mBuffer = nullptr; - mVertexArray = nullptr; + mVertexArray[mCurrentBuffer] = new osg::UByteArray(mNeedVertexCount*sizeof(MyGUI::Vertex)); + + mBuffer[mCurrentBuffer] = new osg::VertexBufferObject; + mBuffer[mCurrentBuffer]->setDataVariance(osg::Object::DYNAMIC); + mBuffer[mCurrentBuffer]->setUsage(GL_DYNAMIC_DRAW); + // NB mBuffer does not own the array + mBuffer[mCurrentBuffer]->setArray(0, mVertexArray[mCurrentBuffer].get()); + + return mVertexArray[mCurrentBuffer]; } -void OSGVertexBuffer::create() +osg::Array* OSGVertexBuffer::getVertexArray() { - MYGUI_PLATFORM_ASSERT(!mBuffer.valid(), "Vertex buffer already exist"); - - mVertexArray = new osg::UByteArray(mNeedVertexCount*sizeof(MyGUI::Vertex)); + return mVertexArray[mCurrentBuffer]; +} - mBuffer = new osg::VertexBufferObject; - mBuffer->setDataVariance(osg::Object::DYNAMIC); - mBuffer->setUsage(GL_DYNAMIC_DRAW); - // NB mBuffer does not own the array - mBuffer->setArray(0, mVertexArray.get()); +osg::VertexBufferObject* OSGVertexBuffer::getVertexBuffer() +{ + return mBuffer[mCurrentBuffer]; } // --------------------------------------------------------------------------- @@ -438,9 +437,9 @@ void RenderManager::doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *text { Drawable::Batch batch; batch.mVertexCount = count; - batch.mVertexBuffer = static_cast(buffer)->getBuffer(); - static_cast(buffer)->markAsQueuedForDrawing(); - batch.mArray = static_cast(buffer)->getArray(); + batch.mVertexBuffer = static_cast(buffer)->getVertexBuffer(); + batch.mArray = static_cast(buffer)->getVertexArray(); + static_cast(buffer)->markUsed(); if (texture) { batch.mTexture = static_cast(texture)->getTexture();