From e295a72d43a589be183e89f80f2106c1b4a1fa29 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 12 Feb 2017 15:57:03 +0100 Subject: [PATCH 1/8] Add align=Center to GUI dialogs (Fixes #2289) --- files/mygui/openmw_alchemy_window.layout | 2 +- files/mygui/openmw_chargen_birth.layout | 2 +- files/mygui/openmw_chargen_class.layout | 2 +- files/mygui/openmw_chargen_class_description.layout | 2 +- files/mygui/openmw_chargen_create_class.layout | 2 +- files/mygui/openmw_chargen_generate_class_result.layout | 2 +- files/mygui/openmw_chargen_race.layout | 2 +- files/mygui/openmw_chargen_review.layout | 2 +- files/mygui/openmw_chargen_select_attribute.layout | 2 +- files/mygui/openmw_chargen_select_skill.layout | 2 +- files/mygui/openmw_chargen_select_specialization.layout | 2 +- files/mygui/openmw_confirmation_dialog.layout | 2 +- files/mygui/openmw_count_window.layout | 2 +- files/mygui/openmw_edit_effect.layout | 2 +- files/mygui/openmw_edit_note.layout | 2 +- files/mygui/openmw_enchanting_dialog.layout | 2 +- files/mygui/openmw_infobox.layout | 2 +- files/mygui/openmw_interactive_messagebox.layout | 2 +- files/mygui/openmw_itemselection_dialog.layout | 2 +- files/mygui/openmw_jail_screen.layout | 2 +- files/mygui/openmw_levelup_dialog.layout | 2 +- files/mygui/openmw_magicselection_dialog.layout | 2 +- files/mygui/openmw_merchantrepair.layout | 2 +- files/mygui/openmw_persuasion_dialog.layout | 2 +- files/mygui/openmw_quickkeys_menu.layout | 2 +- files/mygui/openmw_recharge_dialog.layout | 2 +- files/mygui/openmw_repair.layout | 2 +- files/mygui/openmw_savegame_dialog.layout | 2 +- files/mygui/openmw_spell_buying_window.layout | 2 +- files/mygui/openmw_spellcreation_dialog.layout | 2 +- files/mygui/openmw_text_input.layout | 2 +- files/mygui/openmw_trainingwindow.layout | 2 +- files/mygui/openmw_travel_window.layout | 2 +- files/mygui/openmw_wait_dialog.layout | 2 +- files/mygui/openmw_wait_dialog_progressbar.layout | 2 +- 35 files changed, 35 insertions(+), 35 deletions(-) diff --git a/files/mygui/openmw_alchemy_window.layout b/files/mygui/openmw_alchemy_window.layout index e098800af..ef8296980 100644 --- a/files/mygui/openmw_alchemy_window.layout +++ b/files/mygui/openmw_alchemy_window.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_chargen_birth.layout b/files/mygui/openmw_chargen_birth.layout index d13a5a02d..2375e5277 100644 --- a/files/mygui/openmw_chargen_birth.layout +++ b/files/mygui/openmw_chargen_birth.layout @@ -1,6 +1,6 @@ - + diff --git a/files/mygui/openmw_chargen_class.layout b/files/mygui/openmw_chargen_class.layout index aae3c7035..53a6a6642 100644 --- a/files/mygui/openmw_chargen_class.layout +++ b/files/mygui/openmw_chargen_class.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_chargen_class_description.layout b/files/mygui/openmw_chargen_class_description.layout index eaf754697..3d341eee5 100644 --- a/files/mygui/openmw_chargen_class_description.layout +++ b/files/mygui/openmw_chargen_class_description.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_chargen_create_class.layout b/files/mygui/openmw_chargen_create_class.layout index 1d071e621..5f0b02c1b 100644 --- a/files/mygui/openmw_chargen_create_class.layout +++ b/files/mygui/openmw_chargen_create_class.layout @@ -1,6 +1,6 @@ - + diff --git a/files/mygui/openmw_chargen_generate_class_result.layout b/files/mygui/openmw_chargen_generate_class_result.layout index edbbaeb57..83595fafd 100644 --- a/files/mygui/openmw_chargen_generate_class_result.layout +++ b/files/mygui/openmw_chargen_generate_class_result.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index 1290795ed..58eb6f6f7 100644 --- a/files/mygui/openmw_chargen_race.layout +++ b/files/mygui/openmw_chargen_race.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_chargen_review.layout b/files/mygui/openmw_chargen_review.layout index db55e8754..1099fcd3b 100644 --- a/files/mygui/openmw_chargen_review.layout +++ b/files/mygui/openmw_chargen_review.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_chargen_select_attribute.layout b/files/mygui/openmw_chargen_select_attribute.layout index cd722ef3e..a00577e41 100644 --- a/files/mygui/openmw_chargen_select_attribute.layout +++ b/files/mygui/openmw_chargen_select_attribute.layout @@ -1,6 +1,6 @@ - + diff --git a/files/mygui/openmw_chargen_select_skill.layout b/files/mygui/openmw_chargen_select_skill.layout index 8d4ffdba2..b6e90b688 100644 --- a/files/mygui/openmw_chargen_select_skill.layout +++ b/files/mygui/openmw_chargen_select_skill.layout @@ -1,6 +1,6 @@ - + diff --git a/files/mygui/openmw_chargen_select_specialization.layout b/files/mygui/openmw_chargen_select_specialization.layout index d0b74104b..70c5fdca5 100644 --- a/files/mygui/openmw_chargen_select_specialization.layout +++ b/files/mygui/openmw_chargen_select_specialization.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index 1bedc8372..fbf779cd1 100644 --- a/files/mygui/openmw_confirmation_dialog.layout +++ b/files/mygui/openmw_confirmation_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_count_window.layout b/files/mygui/openmw_count_window.layout index 27b62ebf0..891f9f00c 100644 --- a/files/mygui/openmw_count_window.layout +++ b/files/mygui/openmw_count_window.layout @@ -1,6 +1,6 @@  - + diff --git a/files/mygui/openmw_edit_effect.layout b/files/mygui/openmw_edit_effect.layout index 6123f90a7..387c01231 100644 --- a/files/mygui/openmw_edit_effect.layout +++ b/files/mygui/openmw_edit_effect.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_edit_note.layout b/files/mygui/openmw_edit_note.layout index 652f67f0c..eb2a2789d 100644 --- a/files/mygui/openmw_edit_note.layout +++ b/files/mygui/openmw_edit_note.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_enchanting_dialog.layout b/files/mygui/openmw_enchanting_dialog.layout index b90fc7a77..88e0ec247 100644 --- a/files/mygui/openmw_enchanting_dialog.layout +++ b/files/mygui/openmw_enchanting_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_infobox.layout b/files/mygui/openmw_infobox.layout index 4e70cd2c4..ea9f78614 100644 --- a/files/mygui/openmw_infobox.layout +++ b/files/mygui/openmw_infobox.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_interactive_messagebox.layout b/files/mygui/openmw_interactive_messagebox.layout index a72bebf3a..50bc178ed 100644 --- a/files/mygui/openmw_interactive_messagebox.layout +++ b/files/mygui/openmw_interactive_messagebox.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_itemselection_dialog.layout b/files/mygui/openmw_itemselection_dialog.layout index 5fc286298..5ae30563a 100644 --- a/files/mygui/openmw_itemselection_dialog.layout +++ b/files/mygui/openmw_itemselection_dialog.layout @@ -1,6 +1,6 @@ - + diff --git a/files/mygui/openmw_jail_screen.layout b/files/mygui/openmw_jail_screen.layout index 4385494e1..ef37c73d8 100644 --- a/files/mygui/openmw_jail_screen.layout +++ b/files/mygui/openmw_jail_screen.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_levelup_dialog.layout b/files/mygui/openmw_levelup_dialog.layout index ead181d26..ad0004934 100644 --- a/files/mygui/openmw_levelup_dialog.layout +++ b/files/mygui/openmw_levelup_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_magicselection_dialog.layout b/files/mygui/openmw_magicselection_dialog.layout index bf4cb71d4..5301ecfe9 100644 --- a/files/mygui/openmw_magicselection_dialog.layout +++ b/files/mygui/openmw_magicselection_dialog.layout @@ -1,6 +1,6 @@ - + diff --git a/files/mygui/openmw_merchantrepair.layout b/files/mygui/openmw_merchantrepair.layout index 23ab6008f..de5d0e316 100644 --- a/files/mygui/openmw_merchantrepair.layout +++ b/files/mygui/openmw_merchantrepair.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_persuasion_dialog.layout b/files/mygui/openmw_persuasion_dialog.layout index 6fb298914..d9a673ec2 100644 --- a/files/mygui/openmw_persuasion_dialog.layout +++ b/files/mygui/openmw_persuasion_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_quickkeys_menu.layout b/files/mygui/openmw_quickkeys_menu.layout index d7e976d45..3371b4f49 100644 --- a/files/mygui/openmw_quickkeys_menu.layout +++ b/files/mygui/openmw_quickkeys_menu.layout @@ -1,6 +1,6 @@ - + diff --git a/files/mygui/openmw_recharge_dialog.layout b/files/mygui/openmw_recharge_dialog.layout index 1bf7d9038..9301bec92 100644 --- a/files/mygui/openmw_recharge_dialog.layout +++ b/files/mygui/openmw_recharge_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_repair.layout b/files/mygui/openmw_repair.layout index 9706a2b92..9a349c56b 100644 --- a/files/mygui/openmw_repair.layout +++ b/files/mygui/openmw_repair.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_savegame_dialog.layout b/files/mygui/openmw_savegame_dialog.layout index c97e7f815..40288f0f5 100644 --- a/files/mygui/openmw_savegame_dialog.layout +++ b/files/mygui/openmw_savegame_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_spell_buying_window.layout b/files/mygui/openmw_spell_buying_window.layout index 0350f1e27..73fb6e869 100644 --- a/files/mygui/openmw_spell_buying_window.layout +++ b/files/mygui/openmw_spell_buying_window.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_spellcreation_dialog.layout b/files/mygui/openmw_spellcreation_dialog.layout index 11197bf2a..e14674ad6 100644 --- a/files/mygui/openmw_spellcreation_dialog.layout +++ b/files/mygui/openmw_spellcreation_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_text_input.layout b/files/mygui/openmw_text_input.layout index 012b0a82b..64ec61b02 100644 --- a/files/mygui/openmw_text_input.layout +++ b/files/mygui/openmw_text_input.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_trainingwindow.layout b/files/mygui/openmw_trainingwindow.layout index c58bd0ab3..19c6a6712 100644 --- a/files/mygui/openmw_trainingwindow.layout +++ b/files/mygui/openmw_trainingwindow.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_travel_window.layout b/files/mygui/openmw_travel_window.layout index 3603f7dcb..2d6b1324a 100644 --- a/files/mygui/openmw_travel_window.layout +++ b/files/mygui/openmw_travel_window.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_wait_dialog.layout b/files/mygui/openmw_wait_dialog.layout index 7c065038d..112fa6001 100644 --- a/files/mygui/openmw_wait_dialog.layout +++ b/files/mygui/openmw_wait_dialog.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_wait_dialog_progressbar.layout b/files/mygui/openmw_wait_dialog_progressbar.layout index 93793fd8e..92fcb15cf 100644 --- a/files/mygui/openmw_wait_dialog_progressbar.layout +++ b/files/mygui/openmw_wait_dialog_progressbar.layout @@ -1,7 +1,7 @@ - + From 325bf666533795d777bda39bbe62fba298e979a6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 13 Feb 2017 01:29:22 +0100 Subject: [PATCH 2/8] Return const Land in ESMStore --- apps/openmw/mwrender/globalmap.cpp | 2 +- apps/openmw/mwrender/terrainstorage.cpp | 3 ++- apps/openmw/mwworld/scene.cpp | 4 ++-- apps/openmw/mwworld/store.cpp | 8 ++++---- apps/openmw/mwworld/store.hpp | 4 ++-- components/esm/loadland.cpp | 2 +- components/esm/loadland.hpp | 2 +- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 5cf1ecd36..e89c3d147 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -153,7 +153,7 @@ namespace MWRender { for (int y = mMinY; y <= mMaxY; ++y) { - ESM::Land* land = esmStore.get().search (x,y); + const ESM::Land* land = esmStore.get().search (x,y); if (land) { diff --git a/apps/openmw/mwrender/terrainstorage.cpp b/apps/openmw/mwrender/terrainstorage.cpp index 98386690b..311eb1621 100644 --- a/apps/openmw/mwrender/terrainstorage.cpp +++ b/apps/openmw/mwrender/terrainstorage.cpp @@ -43,7 +43,8 @@ namespace MWRender { const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore(); - ESM::Land* land = esmStore.get().search(cellX, cellY); + + const ESM::Land* land = esmStore.get().search(cellX, cellY); if (!land) return NULL; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 3917518a2..8a3178e6c 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -228,7 +228,7 @@ namespace MWWorld if ((*iter)->getCell()->isExterior()) { - ESM::Land* land = + const ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().get().search( (*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY() @@ -262,7 +262,7 @@ namespace MWWorld // Load terrain physics first... if (cell->getCell()->isExterior()) { - ESM::Land* land = + const ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().get().search( cell->getCell()->getGridX(), cell->getCell()->getGridY() diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index c13f10d9a..ce41ddf94 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -436,7 +436,7 @@ namespace MWWorld { return iterator(mStatic.end()); } - ESM::Land *Store::search(int x, int y) const + const ESM::Land *Store::search(int x, int y) const { ESM::Land land; land.mX = x, land.mY = y; @@ -445,13 +445,13 @@ namespace MWWorld std::lower_bound(mStatic.begin(), mStatic.end(), &land, Compare()); if (it != mStatic.end() && (*it)->mX == x && (*it)->mY == y) { - return const_cast(*it); + return *it; } return 0; } - ESM::Land *Store::find(int x, int y) const + const ESM::Land *Store::find(int x, int y) const { - ESM::Land *ptr = search(x, y); + const ESM::Land *ptr = search(x, y); if (ptr == 0) { std::ostringstream msg; msg << "Land at (" << x << ", " << y << ") not found"; diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 617c3552a..3babea86a 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -242,8 +242,8 @@ namespace MWWorld // Must be threadsafe! Called from terrain background loading threads. // Not a big deal here, since ESM::Land can never be modified or inserted/erased - ESM::Land *search(int x, int y) const; - ESM::Land *find(int x, int y) const; + const ESM::Land *search(int x, int y) const; + const ESM::Land *find(int x, int y) const; RecordId load(ESM::ESMReader &esm); void setUp(); diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index fd69cdacc..d30bfdf49 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -234,7 +234,7 @@ namespace ESM } } - void Land::unloadData() + void Land::unloadData() const { if (mDataLoaded) { diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index a2bf1573e..5598fb616 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -123,7 +123,7 @@ struct Land /** * Frees memory allocated for land data */ - void unloadData(); + void unloadData() const; /// Check if given data type is loaded /// @note We only check data types that *can* be loaded (present in mDataTypes) From e00b420f68b6feb8514a3e1bdb760787838f3f94 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 14 Feb 2017 02:30:21 +0100 Subject: [PATCH 3/8] Move saving of LandData into Land::save --- components/esm/loadland.cpp | 93 ++++++++++++++++++------------------- components/esm/loadland.hpp | 6 --- 2 files changed, 44 insertions(+), 55 deletions(-) diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index d30bfdf49..277190e8c 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -12,51 +12,6 @@ namespace ESM { unsigned int Land::sRecordId = REC_LAND; - void Land::LandData::save(ESMWriter &esm) const - { - if (mDataTypes & Land::DATA_VNML) { - esm.writeHNT("VNML", mNormals, sizeof(mNormals)); - } - if (mDataTypes & Land::DATA_VHGT) { - VHGT offsets; - offsets.mHeightOffset = mHeights[0] / HEIGHT_SCALE; - offsets.mUnk1 = mUnk1; - offsets.mUnk2 = mUnk2; - - float prevY = mHeights[0]; - int number = 0; // avoid multiplication - for (int i = 0; i < LAND_SIZE; ++i) { - float diff = (mHeights[number] - prevY) / HEIGHT_SCALE; - offsets.mHeightData[number] = - (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); - - float prevX = prevY = mHeights[number]; - ++number; - - for (int j = 1; j < LAND_SIZE; ++j) { - diff = (mHeights[number] - prevX) / HEIGHT_SCALE; - offsets.mHeightData[number] = - (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); - - prevX = mHeights[number]; - ++number; - } - } - esm.writeHNT("VHGT", offsets, sizeof(VHGT)); - } - if (mDataTypes & Land::DATA_WNAM) { - esm.writeHNT("WNAM", mWnam, 81); - } - if (mDataTypes & Land::DATA_VCLR) { - esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS); - } - if (mDataTypes & Land::DATA_VTEX) { - uint16_t vtex[LAND_NUM_TEXTURES]; - transposeTextureData(mTextures, vtex); - esm.writeHNT("VTEX", vtex, sizeof(vtex)); - } - } - Land::Land() : mFlags(0) , mX(0) @@ -68,7 +23,7 @@ namespace ESM { } - void Land::LandData::transposeTextureData(const uint16_t *in, uint16_t *out) + void transposeTextureData(const uint16_t *in, uint16_t *out) { int readPos = 0; //bit ugly, but it works for ( int y1 = 0; y1 < 4; y1++ ) @@ -174,8 +129,49 @@ namespace ESM if (mLandData) { - mLandData->save(esm); + if (mDataTypes & Land::DATA_VNML) { + esm.writeHNT("VNML", mLandData->mNormals, sizeof(mLandData->mNormals)); + } + if (mDataTypes & Land::DATA_VHGT) { + VHGT offsets; + offsets.mHeightOffset = mLandData->mHeights[0] / HEIGHT_SCALE; + offsets.mUnk1 = mLandData->mUnk1; + offsets.mUnk2 = mLandData->mUnk2; + + float prevY = mLandData->mHeights[0]; + int number = 0; // avoid multiplication + for (int i = 0; i < LAND_SIZE; ++i) { + float diff = (mLandData->mHeights[number] - prevY) / HEIGHT_SCALE; + offsets.mHeightData[number] = + (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); + + float prevX = prevY = mLandData->mHeights[number]; + ++number; + + for (int j = 1; j < LAND_SIZE; ++j) { + diff = (mLandData->mHeights[number] - prevX) / HEIGHT_SCALE; + offsets.mHeightData[number] = + (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); + + prevX = mLandData->mHeights[number]; + ++number; + } + } + esm.writeHNT("VHGT", offsets, sizeof(VHGT)); + } + if (mDataTypes & Land::DATA_WNAM) { + esm.writeHNT("WNAM", mLandData->mWnam, 81); + } + if (mDataTypes & Land::DATA_VCLR) { + esm.writeHNT("VCLR", mLandData->mColours, 3*LAND_NUM_VERTS); + } + if (mDataTypes & Land::DATA_VTEX) { + uint16_t vtex[LAND_NUM_TEXTURES]; + transposeTextureData(mLandData->mTextures, vtex); + esm.writeHNT("VTEX", vtex, sizeof(vtex)); + } } + } void Land::loadData(int flags) const @@ -191,7 +187,6 @@ namespace ESM // Create storage if nothing is loaded if (mLandData == NULL) { mLandData = new LandData; - mLandData->mDataTypes = mDataTypes; } ESM::ESMReader reader; @@ -229,7 +224,7 @@ namespace ESM if (reader.isNextSub("VTEX")) { uint16_t vtex[LAND_NUM_TEXTURES]; if (condLoad(reader, flags, DATA_VTEX, vtex, sizeof(vtex))) { - LandData::transposeTextureData(vtex, mLandData->mTextures); + transposeTextureData(vtex, mLandData->mTextures); } } } diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 5598fb616..1a39fa727 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -96,18 +96,12 @@ struct Land // 24-bit RGB color for each vertex unsigned char mColours[3 * LAND_NUM_VERTS]; - // DataTypes available in this LandData, accessing data that is not available is an undefined operation - int mDataTypes; - // low-LOD heightmap (used for rendering the global map) signed char mWnam[81]; // ??? short mUnk1; uint8_t mUnk2; - - void save(ESMWriter &esm) const; - static void transposeTextureData(const uint16_t *in, uint16_t *out); }; void load(ESMReader &esm, bool &isDeleted); From ddd66056089b6ff409eaada4b772aa251377c971 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 14 Feb 2017 02:40:41 +0100 Subject: [PATCH 4/8] Move WNAM out of LandData to avoid redundant (de)allocations on startup --- apps/opencs/model/tools/mergestages.cpp | 4 ++-- apps/opencs/model/world/data.cpp | 2 +- apps/openmw/mwrender/globalmap.cpp | 16 ++-------------- components/esm/loadland.cpp | 25 +++++++++++++++---------- components/esm/loadland.hpp | 6 +++--- 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index 02fc551ab..176d35914 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -129,7 +129,7 @@ void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& // make sure record is loaded land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | - ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); + ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX); if (const ESM::Land::LandData *data = land.getLandData (ESM::Land::DATA_VTEX)) { @@ -221,7 +221,7 @@ void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages) const CSMWorld::Land& land = record.get(); land.loadData (ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | - ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); + ESM::Land::DATA_VTEX); CSMWorld::Land newLand (land); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 1cc4a2cbf..da4942eec 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -993,7 +993,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) if (index!=-1/* && !mBase*/) mLand.getRecord (index).get().loadData ( ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | - ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); + ESM::Land::DATA_VTEX); break; } diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index e89c3d147..50ba14770 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -155,16 +155,6 @@ namespace MWRender { const ESM::Land* land = esmStore.get().search (x,y); - if (land) - { - int mask = ESM::Land::DATA_WNAM; - if (!land->isDataLoaded(mask)) - land->loadData(mask); - } - - const ESM::Land::LandData *landData = - land ? land->getLandData (ESM::Land::DATA_WNAM) : 0; - for (int cellY=0; cellYmWnam[vertexY * 9 + vertexX] << 4) / 2048.f; + if (land && (land->mDataTypes & ESM::Land::DATA_WNAM)) + y2 = (land->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f; else y2 = (SCHAR_MIN << 4) / 2048.f; if (y2 < 0) @@ -218,8 +208,6 @@ namespace MWRender } } loadingListener->increaseProgress(); - if (land) - land->unloadData(); } } diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 277190e8c..5e33e6082 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -76,6 +76,9 @@ namespace ESM mContext = esm.getContext(); + mDataLoaded = 0; + mLandData = NULL; + // Skip the land data here. Load it when the cell is loaded. while (esm.hasMoreSubs()) { @@ -91,7 +94,7 @@ namespace ESM mDataTypes |= DATA_VHGT; break; case ESM::FourCC<'W','N','A','M'>::value: - esm.skipHSub(); + esm.getHExact(mWnam, sizeof(mWnam)); mDataTypes |= DATA_WNAM; break; case ESM::FourCC<'V','C','L','R'>::value: @@ -107,9 +110,6 @@ namespace ESM break; } } - - mDataLoaded = 0; - mLandData = NULL; } void Land::save(ESMWriter &esm, bool isDeleted) const @@ -159,9 +159,14 @@ namespace ESM } esm.writeHNT("VHGT", offsets, sizeof(VHGT)); } - if (mDataTypes & Land::DATA_WNAM) { - esm.writeHNT("WNAM", mLandData->mWnam, 81); - } + } + + if (mDataTypes & Land::DATA_WNAM) { + esm.writeHNT("WNAM", mWnam, 81); + } + + if (mLandData) + { if (mDataTypes & Land::DATA_VCLR) { esm.writeHNT("VCLR", mLandData->mColours, 3*LAND_NUM_VERTS); } @@ -216,9 +221,9 @@ namespace ESM } } - if (reader.isNextSub("WNAM")) { - condLoad(reader, flags, DATA_WNAM, mLandData->mWnam, 81); - } + if (reader.isNextSub("WNAM")) + reader.skipHSub(); + if (reader.isNextSub("VCLR")) condLoad(reader, flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS); if (reader.isNextSub("VTEX")) { diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 1a39fa727..bdaf6cce8 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -96,14 +96,14 @@ struct Land // 24-bit RGB color for each vertex unsigned char mColours[3 * LAND_NUM_VERTS]; - // low-LOD heightmap (used for rendering the global map) - signed char mWnam[81]; - // ??? short mUnk1; uint8_t mUnk2; }; + // low-LOD heightmap (used for rendering the global map) + signed char mWnam[81]; + void load(ESMReader &esm, bool &isDeleted); void save(ESMWriter &esm, bool isDeleted = false) const; From 026a05718f2951962a3cdb74f1fba53ae1a9846e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 14 Feb 2017 03:37:45 +0100 Subject: [PATCH 5/8] Construct the WorkQueue in Engine --- apps/openmw/engine.cpp | 11 ++++++++++- apps/openmw/engine.hpp | 6 ++++++ apps/openmw/mwrender/renderingmanager.cpp | 8 ++------ apps/openmw/mwrender/renderingmanager.hpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 4 ++-- apps/openmw/mwworld/worldimp.hpp | 7 ++++++- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f77130960..d8090ea0d 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -24,6 +24,8 @@ #include +#include + #include #include @@ -231,6 +233,8 @@ OMW::Engine::~Engine() delete mScriptContext; mScriptContext = NULL; + mWorkQueue = NULL; + mResourceSystem.reset(); mViewer = NULL; @@ -454,6 +458,11 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) Settings::Manager::getInt("anisotropy", "General") ); + int numThreads = Settings::Manager::getInt("preload num threads", "Cells"); + if (numThreads <= 0) + throw std::runtime_error("Invalid setting: 'preload num threads' must be >0"); + mWorkQueue = new SceneUtil::WorkQueue(numThreads); + // Create input and UI first to set up a bootstrapping environment for // showing a loading screen and keeping the window responsive while doing so @@ -504,7 +513,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) } // Create the world - mEnvironment.setWorld( new MWWorld::World (mViewer, rootNode, mResourceSystem.get(), + mEnvironment.setWorld( new MWWorld::World (mViewer, rootNode, mResourceSystem.get(), mWorkQueue.get(), mFileCollections, mContentFiles, mEncoder, mFallbackMap, mActivationDistanceOverride, mCellName, mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string())); mEnvironment.getWorld()->setupPlayer(); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index a03752b86..11b6ec0a6 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -18,6 +18,11 @@ namespace Resource class ResourceSystem; } +namespace SceneUtil +{ + class WorkQueue; +} + namespace VFS { class Manager; @@ -68,6 +73,7 @@ namespace OMW SDL_Window* mWindow; std::auto_ptr mVFS; std::auto_ptr mResourceSystem; + osg::ref_ptr mWorkQueue; MWBase::Environment mEnvironment; ToUTF8::FromType mEncoding; ToUTF8::Utf8Encoder* mEncoder; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7f5cd23c7..551e20888 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -164,11 +164,12 @@ namespace MWRender Resource::ResourceSystem* mResourceSystem; }; - RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr rootNode, Resource::ResourceSystem* resourceSystem, + RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr rootNode, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const Fallback::Map* fallback, const std::string& resourcePath) : mViewer(viewer) , mRootNode(rootNode) , mResourceSystem(resourceSystem) + , mWorkQueue(workQueue) , mUnrefQueue(new SceneUtil::UnrefQueue) , mFogDepth(0.f) , mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor")) @@ -179,11 +180,6 @@ namespace MWRender , mFieldOfViewOverride(0.f) , mFieldOfViewOverridden(false) { - int numThreads = Settings::Manager::getInt("preload num threads", "Cells"); - if (numThreads <= 0) - throw std::runtime_error("Invalid setting: 'preload num threads' must be >0"); - mWorkQueue = new SceneUtil::WorkQueue(numThreads); - resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem); resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); resourceSystem->getSceneManager()->setForceShaders(Settings::Manager::getBool("force shaders", "Shaders")); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index b9852dafb..eca56f8b5 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -63,7 +63,7 @@ namespace MWRender class RenderingManager : public MWRender::RenderingInterface { public: - RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr rootNode, Resource::ResourceSystem* resourceSystem, + RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr rootNode, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const Fallback::Map* fallback, const std::string& resourcePath); ~RenderingManager(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d03fa263c..399525a8e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -141,7 +141,7 @@ namespace MWWorld World::World ( osgViewer::Viewer* viewer, osg::ref_ptr rootNode, - Resource::ResourceSystem* resourceSystem, + Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const Files::Collections& fileCollections, const std::vector& contentFiles, ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, @@ -155,7 +155,7 @@ namespace MWWorld mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0) { mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode); - mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath); + mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath); mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering, mPhysics)); mRendering->preloadCommonAssets(); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 5d69f2e12..688ff4751 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -34,6 +34,11 @@ namespace Resource class ResourceSystem; } +namespace SceneUtil +{ + class WorkQueue; +} + namespace ESM { struct Position; @@ -180,7 +185,7 @@ namespace MWWorld World ( osgViewer::Viewer* viewer, osg::ref_ptr rootNode, - Resource::ResourceSystem* resourceSystem, + Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const Files::Collections& fileCollections, const std::vector& contentFiles, ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, From 72c6b11cf8140cd947140c10d1e8ecd2981baf8c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 14 Feb 2017 03:55:29 +0100 Subject: [PATCH 6/8] Move global map render to the worker thread --- apps/openmw/engine.cpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 32 +-- apps/openmw/mwgui/mapwindow.hpp | 11 +- apps/openmw/mwgui/windowmanagerimp.cpp | 11 +- apps/openmw/mwgui/windowmanagerimp.hpp | 10 +- apps/openmw/mwrender/globalmap.cpp | 272 ++++++++++++++----------- apps/openmw/mwrender/globalmap.hpp | 19 +- 7 files changed, 217 insertions(+), 140 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d8090ea0d..e8730a4e8 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -496,7 +496,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) guiRoot->setName("GUI Root"); guiRoot->setNodeMask(MWRender::Mask_GUI); rootNode->addChild(guiRoot); - MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), + MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(), mCfgMgr.getLogPath().string() + std::string("/"), myguiResources, mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts, mFallbackMap, Version::getOpenmwVersionDescription(mResDir.string())); diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 4708d6753..8002dc48a 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -622,7 +622,7 @@ namespace MWGui // ------------------------------------------------------------------------------------------ - MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender) + MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue) : WindowPinnableBase("openmw_map_window.layout") , LocalMapBase(customMarkers, localMapRender) , NoDrop(drag, mMainWidget) @@ -632,7 +632,7 @@ namespace MWGui , mGlobal(false) , mEventBoxGlobal(NULL) , mEventBoxLocal(NULL) - , mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot())) + , mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot(), workQueue)) , mEditNoteDialog() { static bool registered = false; @@ -774,19 +774,11 @@ namespace MWGui mLastScrollWindowCoordinates = currentCoordinates; } - void MapWindow::renderGlobalMap(Loading::Listener* loadingListener) + void MapWindow::renderGlobalMap() { - mGlobalMapRender->render(loadingListener); + mGlobalMapRender->render(); mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); - - mGlobalMapTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getBaseTexture())); - mGlobalMapImage->setRenderItemTexture(mGlobalMapTexture.get()); - mGlobalMapImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); - - mGlobalMapOverlayTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getOverlayTexture())); - mGlobalMapOverlay->setRenderItemTexture(mGlobalMapOverlayTexture.get()); - mGlobalMapOverlay->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); } MapWindow::~MapWindow() @@ -940,6 +932,8 @@ namespace MWGui void MapWindow::open() { + ensureGlobalMapLoaded(); + globalMapUpdatePlayer(); } @@ -984,6 +978,20 @@ namespace MWGui rotatingSubskin->setAngle(angle); } + void MapWindow::ensureGlobalMapLoaded() + { + if (!mGlobalMapTexture.get()) + { + mGlobalMapTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getBaseTexture())); + mGlobalMapImage->setRenderItemTexture(mGlobalMapTexture.get()); + mGlobalMapImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); + + mGlobalMapOverlayTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getOverlayTexture())); + mGlobalMapOverlay->setRenderItemTexture(mGlobalMapOverlayTexture.get()); + mGlobalMapOverlay->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); + } + } + void MapWindow::clear() { mMarkers.clear(); diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 977773179..a0136b1c7 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -33,6 +33,11 @@ namespace Loading class Listener; } +namespace SceneUtil +{ + class WorkQueue; +} + namespace MWGui { @@ -193,14 +198,14 @@ namespace MWGui class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop { public: - MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender); + MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue); virtual ~MapWindow(); void setCellName(const std::string& cellName); virtual void setAlpha(float alpha); - void renderGlobalMap(Loading::Listener* loadingListener); + void renderGlobalMap(); /// adds the marker to the global map /// @param name The ESM::Cell::mName @@ -212,6 +217,8 @@ namespace MWGui void setGlobalMapPlayerPosition (float worldX, float worldY); void setGlobalMapPlayerDir(const float x, const float y); + void ensureGlobalMapLoaded(); + virtual void open(); void onFrame(float dt); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index f679da651..937463ecd 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include #include @@ -115,11 +117,12 @@ namespace MWGui { WindowManager::WindowManager( - osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem - , const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, + osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, + const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding, bool exportFonts, const std::map& fallbackMap, const std::string& versionDescription) : mStore(NULL) , mResourceSystem(resourceSystem) + , mWorkQueue(workQueue) , mViewer(viewer) , mConsoleOnlyScripts(consoleOnlyScripts) , mCurrentModals() @@ -285,7 +288,7 @@ namespace MWGui mRecharge = new Recharge(); mMenu = new MainMenu(w, h, mResourceSystem->getVFS(), mVersionDescription); mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup()); - mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender); + mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender, mWorkQueue); trackWindow(mMap, "map"); mStatsWindow = new StatsWindow(mDragAndDrop); trackWindow(mStatsWindow, "stats"); @@ -373,7 +376,7 @@ namespace MWGui void WindowManager::renderWorldMap() { - mMap->renderGlobalMap(mLoadingScreen); + mMap->renderGlobalMap(); } void WindowManager::setNewGame(bool newgame) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 17a2e3855..4e2cef8af 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -9,6 +9,8 @@ #include +#include + #include "../mwbase/windowmanager.hpp" #include @@ -57,6 +59,11 @@ namespace Resource class ResourceSystem; } +namespace SceneUtil +{ + class WorkQueue; +} + namespace SDLUtil { class SDLCursorManager; @@ -119,7 +126,7 @@ namespace MWGui typedef std::pair Faction; typedef std::vector FactionList; - WindowManager(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, + WindowManager(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding, bool exportFonts, const std::map& fallbackMap, const std::string& versionDescription); virtual ~WindowManager(); @@ -382,6 +389,7 @@ namespace MWGui private: const MWWorld::ESMStore* mStore; Resource::ResourceSystem* mResourceSystem; + osg::ref_ptr mWorkQueue; osgMyGUI::Platform* mGuiPlatform; osgViewer::Viewer* mViewer; diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 50ba14770..0d8a7a039 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -15,6 +15,8 @@ #include #include +#include + #include #include "../mwbase/environment.hpp" @@ -95,8 +97,132 @@ namespace namespace MWRender { - GlobalMap::GlobalMap(osg::Group* root) + class CreateMapWorkItem : public SceneUtil::WorkItem + { + public: + CreateMapWorkItem(int width, int height, int minX, int minY, int maxX, int maxY, int cellSize, const MWWorld::Store& landStore) + : mWidth(width), mHeight(height), mMinX(minX), mMinY(minY), mMaxX(maxX), mMaxY(maxY), mCellSize(cellSize), mLandStore(landStore) + { + } + + virtual void doWork() + { + osg::ref_ptr image = new osg::Image; + image->allocateImage(mWidth, mHeight, 1, GL_RGB, GL_UNSIGNED_BYTE); + unsigned char* data = image->data(); + + osg::ref_ptr alphaImage = new osg::Image; + alphaImage->allocateImage(mWidth, mHeight, 1, GL_ALPHA, GL_UNSIGNED_BYTE); + unsigned char* alphaData = alphaImage->data(); + + for (int x = mMinX; x <= mMaxX; ++x) + { + for (int y = mMinY; y <= mMaxY; ++y) + { + const ESM::Land* land = mLandStore.search (x,y); + + for (int cellY=0; cellY(float(cellX)/float(mCellSize) * 9); + int vertexY = static_cast(float(cellY) / float(mCellSize) * 9); + + int texelX = (x-mMinX) * mCellSize + cellX; + int texelY = (y-mMinY) * mCellSize + cellY; + + unsigned char r,g,b; + + float y2 = 0; + if (land && (land->mDataTypes & ESM::Land::DATA_WNAM)) + y2 = (land->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f; + else + y2 = (SCHAR_MIN << 4) / 2048.f; + if (y2 < 0) + { + r = static_cast(14 * y2 + 38); + g = static_cast(20 * y2 + 56); + b = static_cast(18 * y2 + 51); + } + else if (y2 < 0.3f) + { + if (y2 < 0.1f) + y2 *= 8.f; + else + { + y2 -= 0.1f; + y2 += 0.8f; + } + r = static_cast(66 - 32 * y2); + g = static_cast(48 - 23 * y2); + b = static_cast(33 - 16 * y2); + } + else + { + y2 -= 0.3f; + y2 *= 1.428f; + r = static_cast(34 - 29 * y2); + g = static_cast(25 - 20 * y2); + b = static_cast(17 - 12 * y2); + } + + data[texelY * mWidth * 3 + texelX * 3] = r; + data[texelY * mWidth * 3 + texelX * 3+1] = g; + data[texelY * mWidth * 3 + texelX * 3+2] = b; + + alphaData[texelY * mWidth+ texelX] = (y2 < 0) ? static_cast(0) : static_cast(255); + } + } + } + } + + mBaseTexture = new osg::Texture2D; + mBaseTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + mBaseTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + mBaseTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + mBaseTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + mBaseTexture->setImage(image); + mBaseTexture->setResizeNonPowerOfTwoHint(false); + + mAlphaTexture = new osg::Texture2D; + mAlphaTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + mAlphaTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + mAlphaTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + mAlphaTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + mAlphaTexture->setImage(alphaImage); + mAlphaTexture->setResizeNonPowerOfTwoHint(false); + + mOverlayImage = new osg::Image; + mOverlayImage->allocateImage(mWidth, mHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE); + assert(mOverlayImage->isDataContiguous()); + + memset(mOverlayImage->data(), 0, mOverlayImage->getTotalSizeInBytes()); + + mOverlayTexture = new osg::Texture2D; + mOverlayTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + mOverlayTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + mOverlayTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + mOverlayTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + mOverlayTexture->setResizeNonPowerOfTwoHint(false); + mOverlayTexture->setInternalFormat(GL_RGBA); + mOverlayTexture->setTextureSize(mWidth, mHeight); + } + + int mWidth, mHeight; + int mMinX, mMinY, mMaxX, mMaxY; + int mCellSize; + const MWWorld::Store& mLandStore; + + osg::ref_ptr mBaseTexture; + osg::ref_ptr mAlphaTexture; + + osg::ref_ptr mOverlayImage; + osg::ref_ptr mOverlayTexture; + }; + + GlobalMap::GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue) : mRoot(root) + , mWorkQueue(workQueue) , mWidth(0) , mHeight(0) , mMinX(0), mMaxX(0) @@ -114,7 +240,7 @@ namespace MWRender removeCamera(*it); } - void GlobalMap::render (Loading::Listener* loadingListener) + void GlobalMap::render () { const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore(); @@ -136,100 +262,8 @@ namespace MWRender mWidth = mCellSize*(mMaxX-mMinX+1); mHeight = mCellSize*(mMaxY-mMinY+1); - loadingListener->loadingOn(); - loadingListener->setLabel("Creating map"); - loadingListener->setProgressRange((mMaxX-mMinX+1) * (mMaxY-mMinY+1)); - loadingListener->setProgress(0); - - osg::ref_ptr image = new osg::Image; - image->allocateImage(mWidth, mHeight, 1, GL_RGB, GL_UNSIGNED_BYTE); - unsigned char* data = image->data(); - - osg::ref_ptr alphaImage = new osg::Image; - alphaImage->allocateImage(mWidth, mHeight, 1, GL_ALPHA, GL_UNSIGNED_BYTE); - unsigned char* alphaData = alphaImage->data(); - - for (int x = mMinX; x <= mMaxX; ++x) - { - for (int y = mMinY; y <= mMaxY; ++y) - { - const ESM::Land* land = esmStore.get().search (x,y); - - for (int cellY=0; cellY(float(cellX)/float(mCellSize) * 9); - int vertexY = static_cast(float(cellY) / float(mCellSize) * 9); - - int texelX = (x-mMinX) * mCellSize + cellX; - int texelY = (y-mMinY) * mCellSize + cellY; - - unsigned char r,g,b; - - float y2 = 0; - if (land && (land->mDataTypes & ESM::Land::DATA_WNAM)) - y2 = (land->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f; - else - y2 = (SCHAR_MIN << 4) / 2048.f; - if (y2 < 0) - { - r = static_cast(14 * y2 + 38); - g = static_cast(20 * y2 + 56); - b = static_cast(18 * y2 + 51); - } - else if (y2 < 0.3f) - { - if (y2 < 0.1f) - y2 *= 8.f; - else - { - y2 -= 0.1f; - y2 += 0.8f; - } - r = static_cast(66 - 32 * y2); - g = static_cast(48 - 23 * y2); - b = static_cast(33 - 16 * y2); - } - else - { - y2 -= 0.3f; - y2 *= 1.428f; - r = static_cast(34 - 29 * y2); - g = static_cast(25 - 20 * y2); - b = static_cast(17 - 12 * y2); - } - - data[texelY * mWidth * 3 + texelX * 3] = r; - data[texelY * mWidth * 3 + texelX * 3+1] = g; - data[texelY * mWidth * 3 + texelX * 3+2] = b; - - alphaData[texelY * mWidth+ texelX] = (y2 < 0) ? static_cast(0) : static_cast(255); - } - } - loadingListener->increaseProgress(); - } - } - - mBaseTexture = new osg::Texture2D; - mBaseTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - mBaseTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - mBaseTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - mBaseTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - mBaseTexture->setImage(image); - mBaseTexture->setResizeNonPowerOfTwoHint(false); - - mAlphaTexture = new osg::Texture2D; - mAlphaTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - mAlphaTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - mAlphaTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - mAlphaTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - mAlphaTexture->setImage(alphaImage); - mAlphaTexture->setResizeNonPowerOfTwoHint(false); - - clear(); - - loadingListener->loadingOff(); + mWorkItem = new CreateMapWorkItem(mWidth, mHeight, mMinX, mMinY, mMaxX, mMaxY, mCellSize, esmStore.get()); + mWorkQueue->addWorkItem(mWorkItem); } void GlobalMap::worldPosToImageSpace(float x, float z, float& imageX, float& imageY) @@ -334,6 +368,8 @@ namespace MWRender void GlobalMap::exploreCell(int cellX, int cellY, osg::ref_ptr localMapTexture) { + ensureLoaded(); + if (!localMapTexture) return; @@ -348,25 +384,9 @@ namespace MWRender void GlobalMap::clear() { - if (!mOverlayImage) - { - mOverlayImage = new osg::Image; - mOverlayImage->allocateImage(mWidth, mHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE); - assert(mOverlayImage->isDataContiguous()); - } - memset(mOverlayImage->data(), 0, mOverlayImage->getTotalSizeInBytes()); + ensureLoaded(); - if (!mOverlayTexture) - { - mOverlayTexture = new osg::Texture2D; - mOverlayTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - mOverlayTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - mOverlayTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - mOverlayTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - mOverlayTexture->setResizeNonPowerOfTwoHint(false); - mOverlayTexture->setInternalFormat(GL_RGBA); - mOverlayTexture->setTextureSize(mWidth, mHeight); - } + memset(mOverlayImage->data(), 0, mOverlayImage->getTotalSizeInBytes()); mPendingImageDest.clear(); @@ -377,6 +397,8 @@ namespace MWRender void GlobalMap::write(ESM::GlobalMap& map) { + ensureLoaded(); + map.mBounds.mMinX = mMinX; map.mBounds.mMaxX = mMaxX; map.mBounds.mMinY = mMinY; @@ -417,6 +439,8 @@ namespace MWRender void GlobalMap::read(ESM::GlobalMap& map) { + ensureLoaded(); + const ESM::GlobalMap::Bounds& bounds = map.mBounds; if (bounds.mMaxX-bounds.mMinX < 0) @@ -513,14 +537,33 @@ namespace MWRender osg::ref_ptr GlobalMap::getBaseTexture() { + ensureLoaded(); return mBaseTexture; } osg::ref_ptr GlobalMap::getOverlayTexture() { + ensureLoaded(); return mOverlayTexture; } + void GlobalMap::ensureLoaded() + { + if (mWorkItem) + { + mWorkItem->waitTillDone(); + + mOverlayImage = mWorkItem->mOverlayImage; + mBaseTexture = mWorkItem->mBaseTexture; + mAlphaTexture = mWorkItem->mAlphaTexture; + mOverlayTexture = mWorkItem->mOverlayTexture; + + requestOverlayTextureUpdate(0, 0, mWidth, mHeight, osg::ref_ptr(), true, false); + + mWorkItem = NULL; + } + } + void GlobalMap::markForRemoval(osg::Camera *camera) { CameraVector::iterator found = std::find(mActiveCameras.begin(), mActiveCameras.end(), camera); @@ -549,6 +592,7 @@ namespace MWRender continue; } + ensureLoaded(); mOverlayImage->copySubImage(imageDest.mX, imageDest.mY, 0, imageDest.mImage); it = mPendingImageDest.erase(it); diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index 1c44439fd..f19f4a91f 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -14,26 +14,28 @@ namespace osg class Camera; } -namespace Loading +namespace ESM { - class Listener; + struct GlobalMap; } -namespace ESM +namespace SceneUtil { - struct GlobalMap; + class WorkQueue; } namespace MWRender { + class CreateMapWorkItem; + class GlobalMap { public: - GlobalMap(osg::Group* root); + GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue); ~GlobalMap(); - void render(Loading::Listener* loadingListener); + void render(); int getWidth() const { return mWidth; } int getHeight() const { return mHeight; } @@ -69,6 +71,8 @@ namespace MWRender osg::ref_ptr getBaseTexture(); osg::ref_ptr getOverlayTexture(); + void ensureLoaded(); + private: /** * Request rendering a 2d quad onto mOverlayTexture. @@ -116,6 +120,9 @@ namespace MWRender // CPU copy of overlay osg::ref_ptr mOverlayImage; + osg::ref_ptr mWorkQueue; + osg::ref_ptr mWorkItem; + int mWidth; int mHeight; From a495b9b8845ce03bd21f021f6014e4a3b7d76df0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 14 Feb 2017 07:10:01 +0100 Subject: [PATCH 7/8] Fix wasteful allocations in Store::search --- apps/openmw/mwworld/store.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index ce41ddf94..922144814 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -38,6 +38,12 @@ namespace } return x->mX < y->mX; } + bool operator()(const ESM::Land *x, const std::pair& y) { + if (x->mX == y.first) { + return x->mY < y.second; + } + return x->mX < y.first; + } }; } @@ -438,11 +444,10 @@ namespace MWWorld } const ESM::Land *Store::search(int x, int y) const { - ESM::Land land; - land.mX = x, land.mY = y; + std::pair comp(x,y); std::vector::const_iterator it = - std::lower_bound(mStatic.begin(), mStatic.end(), &land, Compare()); + std::lower_bound(mStatic.begin(), mStatic.end(), comp, Compare()); if (it != mStatic.end() && (*it)->mX == x && (*it)->mY == y) { return *it; From 183c46b0ef06e5010eee1744b9713e533dd75ca2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 14 Feb 2017 07:57:48 +0100 Subject: [PATCH 8/8] Fix summoning effects --- apps/openmw/mwmechanics/actors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 418f53422..020632c7d 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -763,7 +763,7 @@ namespace MWMechanics bool hasSummonEffect = false; for (MagicEffects::Collection::const_iterator it = effects.begin(); it != effects.end(); ++it) - if (it->first.mId >= ESM::MagicEffect::SummonScamp && it->first.mId <= ESM::MagicEffect::SummonStormAtronach) + if (isSummoningEffect(it->first.mId)) hasSummonEffect = true; if (!creatureStats.getSummonedCreatureMap().empty() || !creatureStats.getSummonedCreatureGraveyard().empty() || hasSummonEffect)