From 360d786ff2a203c7363675d432697ff42e39374a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 7 Dec 2017 23:48:34 +0100 Subject: [PATCH 01/24] CS: Add rendering prefs and camera FOV --- apps/opencs/model/prefs/state.cpp | 3 +++ apps/opencs/view/prefs/dialogue.cpp | 1 - apps/opencs/view/render/scenewidget.cpp | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 1f84c5a87..be6534089 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -192,6 +192,9 @@ void CSMPrefs::State::declare() setRange (0.001, 100.0); declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1); + declareCategory ("Rendering"); + declareDouble ("camera-fov", "Camera FOV", 90.).setPrecision(5).setRange(10.0, 160.0); + declareCategory ("Tooltips"); declareBool ("scene", "Show Tooltips in 3D scenes", true); declareBool ("scene-hide-basic", "Hide basic 3D scenes tooltips", false); diff --git a/apps/opencs/view/prefs/dialogue.cpp b/apps/opencs/view/prefs/dialogue.cpp index 960ca74bc..1f5772f18 100644 --- a/apps/opencs/view/prefs/dialogue.cpp +++ b/apps/opencs/view/prefs/dialogue.cpp @@ -84,7 +84,6 @@ CSVPrefs::Dialogue::~Dialogue() void CSVPrefs::Dialogue::closeEvent (QCloseEvent *event) { QMainWindow::closeEvent (event); - CSMPrefs::State::get().save(); } diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 11c7f5926..46bbb29dd 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -66,7 +66,11 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f) mView->getCamera()->setGraphicsContext(window); mView->getCamera()->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) ); mView->getCamera()->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); - mView->getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast(traits->width)/static_cast(traits->height), 1.0f, 10000.0f ); + + mView->getCamera()->setProjectionMatrixAsPerspective( + CSMPrefs::get()["Rendering"]["camera-fov"].toDouble(), + static_cast(traits->width)/static_cast(traits->height), + 1.0f, 10000.0f); SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager; lightMgr->setStartLight(1); From 7d36dd68dcc4e3b245a119a948959b9f91f37752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 7 Dec 2017 23:52:05 +0100 Subject: [PATCH 02/24] CS: Make orbit camera not change roll --- apps/opencs/view/render/cameracontroller.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index 7b802b0ef..cb1278805 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -673,6 +673,7 @@ namespace CSVRender { osg::Vec3d eye, center, up; getCamera()->getViewMatrixAsLookAt(eye, center, up); + up = osg::Vec3(0,0,1); osg::Quat rotation = osg::Quat(value, up); osg::Vec3d oldOffset = eye - mCenter; @@ -685,6 +686,7 @@ namespace CSVRender { osg::Vec3d eye, center, up; getCamera()->getViewMatrixAsLookAt(eye, center, up); + up = osg::Vec3(0,0,1); osg::Vec3d forward = center - eye; osg::Quat rotation = osg::Quat(value, up ^ forward); From cfdc6c788ed33d9a5dc5f3b7c2a2b687769f3f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 8 Dec 2017 00:05:50 +0100 Subject: [PATCH 03/24] CS: Make camera FOV change dynamically --- apps/opencs/view/render/scenewidget.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 46bbb29dd..7d3ac3f1c 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -374,6 +374,13 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting) { mOrbitCamControl->setOrbitSpeedMultiplier(setting->toDouble()); } + else if (*setting=="Rendering/camera-fov") + { + mView->getCamera()->setProjectionMatrixAsPerspective( + setting->toDouble(), + static_cast(width())/static_cast(height()), + 1.0f, 10000.0f); + } } void SceneWidget::selectNavigationMode (const std::string& mode) From 5e076ee01519cf06f79cc59a717a8acd3298a9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 8 Dec 2017 00:19:05 +0100 Subject: [PATCH 04/24] CS: Fix camera orbit with arbitrary roll --- apps/opencs/view/render/cameracontroller.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index cb1278805..f0158fe28 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -673,12 +673,13 @@ namespace CSVRender { osg::Vec3d eye, center, up; getCamera()->getViewMatrixAsLookAt(eye, center, up); - up = osg::Vec3(0,0,1); + osg::Vec3 absoluteUp = osg::Vec3(0,0,1); - osg::Quat rotation = osg::Quat(value, up); + osg::Quat rotation = osg::Quat(value, absoluteUp); osg::Vec3d oldOffset = eye - mCenter; osg::Vec3d newOffset = rotation * oldOffset; + up = rotation * up; getCamera()->setViewMatrixAsLookAt(mCenter + newOffset, mCenter, up); } @@ -686,13 +687,14 @@ namespace CSVRender { osg::Vec3d eye, center, up; getCamera()->getViewMatrixAsLookAt(eye, center, up); - up = osg::Vec3(0,0,1); + osg::Vec3 absoluteUp = osg::Vec3(0,0,1); osg::Vec3d forward = center - eye; - osg::Quat rotation = osg::Quat(value, up ^ forward); + osg::Quat rotation = osg::Quat(value, absoluteUp ^ forward); osg::Vec3d oldOffset = eye - mCenter; osg::Vec3d newOffset = rotation * oldOffset; + up = rotation * up; getCamera()->setViewMatrixAsLookAt(mCenter + newOffset, mCenter, up); } From aecf74e7bbeca9dae1d19444535b511f3df7f473 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 8 Dec 2017 07:00:04 -0800 Subject: [PATCH 05/24] Don't throw exceptions from the audio decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 190 ++++++++++++---------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 18 +- apps/openmw/mwsound/movieaudiofactory.cpp | 32 ++-- apps/openmw/mwsound/openal_output.cpp | 14 +- apps/openmw/mwsound/sound_decoder.hpp | 4 +- 5 files changed, 146 insertions(+), 112 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 1f1834761..12ea84a42 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -11,11 +11,6 @@ namespace MWSound { -void FFmpeg_Decoder::fail(const std::string &msg) -{ - throw std::runtime_error("FFmpeg exception: "+msg); -} - int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size) { try @@ -33,7 +28,8 @@ int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size) int FFmpeg_Decoder::writePacket(void *, uint8_t *, int) { - throw std::runtime_error("can't write to read-only stream"); + std::cerr<< "can't write to read-only stream" <get(fname); + try + { + mDataStream = mResourceMgr->get(fname); - if((mFormatCtx=avformat_alloc_context()) == NULL) - fail("Failed to allocate context"); + if((mFormatCtx=avformat_alloc_context()) == NULL) + throw std::runtime_error("Failed to allocate context"); - mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); - if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) - { - // "Note that a user-supplied AVFormatContext will be freed on failure". - if (mFormatCtx) + mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); + if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) { - if (mFormatCtx->pb != NULL) + // "Note that a user-supplied AVFormatContext will be freed on failure". + if (mFormatCtx) { - if (mFormatCtx->pb->buffer != NULL) + if (mFormatCtx->pb != NULL) { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; + if (mFormatCtx->pb->buffer != NULL) + { + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; + } + av_free(mFormatCtx->pb); + mFormatCtx->pb = NULL; } - av_free(mFormatCtx->pb); - mFormatCtx->pb = NULL; + avformat_free_context(mFormatCtx); } - avformat_free_context(mFormatCtx); + mFormatCtx = NULL; + throw std::runtime_error("Failed to allocate input stream"); } - mFormatCtx = NULL; - fail("Failed to allocate input stream"); - } - try - { if(avformat_find_stream_info(mFormatCtx, NULL) < 0) - fail("Failed to find stream info in "+fname); + throw std::runtime_error("Failed to find stream info in "+fname); for(size_t j = 0;j < mFormatCtx->nb_streams;j++) { @@ -224,23 +220,45 @@ void FFmpeg_Decoder::open(const std::string &fname) } } if(!mStream) - fail("No audio streams in "+fname); + throw std::runtime_error("No audio streams in "+fname); (*mStream)->codec->request_sample_fmt = (*mStream)->codec->sample_fmt; AVCodec *codec = avcodec_find_decoder((*mStream)->codec->codec_id); if(!codec) { - std::stringstream ss("No codec found for id "); - ss << (*mStream)->codec->codec_id; - fail(ss.str()); + std::string ss = "No codec found for id " + + std::to_string((*mStream)->codec->codec_id); + throw std::runtime_error(ss); } if(avcodec_open2((*mStream)->codec, codec, NULL) < 0) - fail("Failed to open audio codec " + std::string(codec->long_name)); + throw std::runtime_error(std::string("Failed to open audio codec ") + + codec->long_name); mFrame = av_frame_alloc(); + + if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || + (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support + else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) + mOutputSampleFormat = AV_SAMPLE_FMT_U8; + else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + else + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + + mOutputChannelLayout = (*mStream)->codec->channel_layout; + if(mOutputChannelLayout == 0) + mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels); + + return true; } - catch(std::exception&) + catch(std::exception &e) + { + std::cerr<< "Could not open audio file: "<codec); @@ -248,15 +266,15 @@ void FFmpeg_Decoder::open(const std::string &fname) if (mFormatCtx->pb->buffer != NULL) { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; } av_free(mFormatCtx->pb); mFormatCtx->pb = NULL; avformat_close_input(&mFormatCtx); - throw; } + return false; } void FFmpeg_Decoder::close() @@ -274,18 +292,18 @@ void FFmpeg_Decoder::close() { if (mFormatCtx->pb != NULL) { - // mFormatCtx->pb->buffer must be freed by hand, - // if not, valgrind will show memleak, see: - // - // https://trac.ffmpeg.org/ticket/1357 - // - if (mFormatCtx->pb->buffer != NULL) - { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; - } - av_free(mFormatCtx->pb); - mFormatCtx->pb = NULL; + // mFormatCtx->pb->buffer must be freed by hand, + // if not, valgrind will show memleak, see: + // + // https://trac.ffmpeg.org/ticket/1357 + // + if (mFormatCtx->pb->buffer != NULL) + { + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; + } + av_free(mFormatCtx->pb); + mFormatCtx->pb = NULL; } avformat_close_input(&mFormatCtx); } @@ -298,19 +316,13 @@ std::string FFmpeg_Decoder::getName() return mFormatCtx->filename; } -void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { if(!mStream) - fail("No audio stream info"); - - if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) - mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) - mOutputSampleFormat = AV_SAMPLE_FMT_U8; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) - mOutputSampleFormat = AV_SAMPLE_FMT_S16; - else - mOutputSampleFormat = AV_SAMPLE_FMT_S16; + { + std::cerr<< "No audio stream info" <codec->channel_layout; - - if(ch_layout == 0) - ch_layout = av_get_default_channel_layout((*mStream)->codec->channels); - - mOutputChannelLayout = ch_layout; - if (ch_layout == AV_CH_LAYOUT_5POINT1 || ch_layout == AV_CH_LAYOUT_7POINT1 - || ch_layout == AV_CH_LAYOUT_QUAD) // FIXME: check for AL_EXT_MCFORMATS support - mOutputChannelLayout = AV_CH_LAYOUT_STEREO; - else if (ch_layout != AV_CH_LAYOUT_MONO - && ch_layout != AV_CH_LAYOUT_STEREO) - mOutputChannelLayout = AV_CH_LAYOUT_STEREO; - if(mOutputChannelLayout == AV_CH_LAYOUT_MONO) *chans = ChannelConfig_Mono; else if(mOutputChannelLayout == AV_CH_LAYOUT_STEREO) @@ -347,13 +346,27 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * char str[1024]; av_get_channel_layout_string(str, sizeof(str), (*mStream)->codec->channels, (*mStream)->codec->channel_layout); - fail(std::string("Unsupported channel layout: ")+str); + std::cerr<< "Unsupported channel layout: "<codec->channels == 1) + { + mOutputChannelLayout = AV_CH_LAYOUT_MONO; + *chans = ChannelConfig_Mono; + } + else + { + mOutputChannelLayout = AV_CH_LAYOUT_STEREO; + *chans = ChannelConfig_Stereo; + } } *samplerate = (*mStream)->codec->sample_rate; + int64_t ch_layout = (*mStream)->codec->channel_layout; + if(ch_layout == 0) + ch_layout = av_get_default_channel_layout((*mStream)->codec->channels); - if(mOutputSampleFormat != (*mStream)->codec->sample_fmt - || mOutputChannelLayout != ch_layout) + if(mOutputSampleFormat != (*mStream)->codec->sample_fmt || + mOutputChannelLayout != ch_layout) { mSwr = swr_alloc_set_opts(mSwr, // SwrContext mOutputChannelLayout, // output ch layout @@ -365,24 +378,37 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * 0, // logging level offset NULL); // log context if(!mSwr) - fail(std::string("Couldn't allocate SwrContext")); + { + std::cerr<< "Couldn't allocate SwrContext" < &output) { if(!mStream) - fail("No audio stream"); + { + std::cerr<< "No audio stream" < &output); - virtual size_t getSampleOffset(); - - void fail(const std::string &msg); + size_t read(char *buffer, size_t bytes) override; + void readAll(std::vector &output) override; + size_t getSampleOffset() override; FFmpeg_Decoder& operator=(const FFmpeg_Decoder &rhs); FFmpeg_Decoder(const FFmpeg_Decoder &rhs); diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index f54ab5c06..188514f85 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -1,5 +1,7 @@ #include "movieaudiofactory.hpp" +#include + #include #include @@ -13,7 +15,7 @@ namespace MWSound { class MovieAudioDecoder; - class MWSoundDecoderBridge : public Sound_Decoder + class MWSoundDecoderBridge final : public Sound_Decoder { public: MWSoundDecoderBridge(MWSound::MovieAudioDecoder* decoder) @@ -25,12 +27,12 @@ namespace MWSound private: MWSound::MovieAudioDecoder* mDecoder; - virtual void open(const std::string &fname); - virtual void close(); - virtual std::string getName(); - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); - virtual size_t read(char *buffer, size_t bytes); - virtual size_t getSampleOffset(); + bool open(const std::string &fname) override; + void close() override; + std::string getName() override; + bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; + size_t read(char *buffer, size_t bytes) override; + size_t getSampleOffset() override; }; class MovieAudioDecoder : public Video::MovieAudioDecoder @@ -96,9 +98,9 @@ namespace MWSound }; - void MWSoundDecoderBridge::open(const std::string &fname) + bool MWSoundDecoderBridge::open(const std::string &fname) { - throw std::runtime_error("unimplemented"); + return false; } void MWSoundDecoderBridge::close() {} @@ -107,7 +109,7 @@ namespace MWSound return mDecoder->getStreamName(); } - void MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) + bool MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { *samplerate = mDecoder->getOutputSampleRate(); @@ -124,9 +126,8 @@ namespace MWSound *chans = ChannelConfig_Quad; else { - std::stringstream error; - error << "Unsupported channel layout: " << outputChannelLayout; - throw std::runtime_error(error.str()); + std::cerr<< "Unsupported channel layout: "<getOutputSampleFormat(); @@ -140,8 +141,11 @@ namespace MWSound { char str[1024]; av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat); - throw std::runtime_error(std::string("Unsupported sample format: ") + str); + std::cerr<< "Unsupported sample format: "<getInfo(&mSampleRate, &chans, &type); + if(!mDecoder->getInfo(&mSampleRate, &chans, &type)) + return false; mFormat = getALFormat(chans, type); if(!mFormat) return false; @@ -948,14 +949,18 @@ std::pair OpenAL_Output::loadSound(const std::string &fname DecoderPtr decoder = mManager.getDecoder(); // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. if(decoder->mResourceMgr->exists(fname)) - decoder->open(fname); + { + if(!decoder->open(fname)) + return std::make_pair(nullptr, 0); + } else { std::string file = fname; std::string::size_type pos = file.rfind('.'); if(pos != std::string::npos) file = file.substr(0, pos)+".mp3"; - decoder->open(file); + if(!decoder->open(file)) + return std::make_pair(nullptr, 0); } std::vector data; @@ -964,7 +969,8 @@ std::pair OpenAL_Output::loadSound(const std::string &fname ALenum format; int srate; - decoder->getInfo(&srate, &chans, &type); + if(!decoder->getInfo(&srate, &chans, &type)) + return std::make_pair(nullptr, 0); format = getALFormat(chans, type); if(!format) return std::make_pair(nullptr, 0); diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 34bae87d7..57edb1393 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -34,11 +34,11 @@ namespace MWSound { const VFS::Manager* mResourceMgr; - virtual void open(const std::string &fname) = 0; + virtual bool open(const std::string &fname) = 0; virtual void close() = 0; virtual std::string getName() = 0; - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; + virtual bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; virtual size_t read(char *buffer, size_t bytes) = 0; virtual void readAll(std::vector &output); From bfad5ebde451bb0cab4bcb137621d3cf61197024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 8 Dec 2017 17:42:20 +0100 Subject: [PATCH 06/24] CS: Fix camera orbit control with keys --- apps/opencs/view/render/cameracontroller.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index f0158fe28..abf68ef93 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -690,7 +690,9 @@ namespace CSVRender osg::Vec3 absoluteUp = osg::Vec3(0,0,1); osg::Vec3d forward = center - eye; - osg::Quat rotation = osg::Quat(value, absoluteUp ^ forward); + + osg::Vec3d axis = absoluteUp ^ forward * (up.z() < 0.0 ? -1.0 : 1.0); + osg::Quat rotation = osg::Quat(value,axis); osg::Vec3d oldOffset = eye - mCenter; osg::Vec3d newOffset = rotation * oldOffset; From 1b77e3ed627afb917d6d4d5ad219dcb6d2587675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 8 Dec 2017 18:18:27 +0100 Subject: [PATCH 07/24] CS: Add ortho camera setting --- apps/opencs/model/prefs/state.cpp | 2 ++ apps/opencs/view/render/scenewidget.cpp | 33 +++++++++++++++++++------ apps/opencs/view/render/scenewidget.hpp | 2 ++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index be6534089..f4ba134d0 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -194,6 +194,8 @@ void CSMPrefs::State::declare() declareCategory ("Rendering"); declareDouble ("camera-fov", "Camera FOV", 90.).setPrecision(5).setRange(10.0, 160.0); + declareBool ("camera-ortho", "Orthographic projection for camera", false); + declareDouble ("camera-ortho-size", "Orthographic projection size parameter", 100.0).setPrecision(5).setRange(0.0, 1000.0); declareCategory ("Tooltips"); declareBool ("scene", "Show Tooltips in 3D scenes", true); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 7d3ac3f1c..a151c638e 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -67,10 +67,7 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f) mView->getCamera()->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) ); mView->getCamera()->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); - mView->getCamera()->setProjectionMatrixAsPerspective( - CSMPrefs::get()["Rendering"]["camera-fov"].toDouble(), - static_cast(traits->width)/static_cast(traits->height), - 1.0f, 10000.0f); + updateCameraParameters(); SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager; lightMgr->setStartLight(1); @@ -374,12 +371,34 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting) { mOrbitCamControl->setOrbitSpeedMultiplier(setting->toDouble()); } - else if (*setting=="Rendering/camera-fov") + else if (*setting=="Rendering/camera-fov" || + *setting=="Rendering/camera-ortho" || + *setting=="Rendering/camera-ortho-size") { + updateCameraParameters(); + } +} + +void RenderWidget::updateCameraParameters() +{ + const float near = 1.0; + const float far = 1000.0; + + if (CSMPrefs::get()["Rendering"]["camera-ortho"].isTrue()) + { + const float size = CSMPrefs::get()["Rendering"]["camera-ortho-size"].toDouble(); + const float half_w = size / 100.0 * static_cast(width()); + const float half_h = size / 100.0 * static_cast(height()); + + mView->getCamera()->setProjectionMatrixAsOrtho( + -half_w, half_w, -half_h, half_h, near, far); + } + else + { mView->getCamera()->setProjectionMatrixAsPerspective( - setting->toDouble(), + CSMPrefs::get()["Rendering"]["camera-fov"].toDouble(), static_cast(width())/static_cast(height()), - 1.0f, 10000.0f); + near, far); } } diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index cc3191c81..af7a6f1ec 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -64,6 +64,8 @@ namespace CSVRender osg::ref_ptr mView; osg::ref_ptr mRootNode; + void updateCameraParameters(); + QTimer mTimer; protected slots: From d85f8deaa3b0fd802da2e3713d9d829ab700bd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 8 Dec 2017 20:51:40 +0100 Subject: [PATCH 08/24] CS: Add fixed roll setting, plus ortho fix --- apps/opencs/model/prefs/state.cpp | 3 ++- apps/opencs/view/render/cameracontroller.cpp | 25 +++++++++++++++----- apps/opencs/view/render/cameracontroller.hpp | 4 ++++ apps/opencs/view/render/scenewidget.cpp | 16 +++++++++---- apps/opencs/view/render/scenewidget.hpp | 2 +- 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index f4ba134d0..9463ae081 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -180,6 +180,7 @@ void CSMPrefs::State::declare() declareDouble ("navi-free-speed-mult", "Free Camera Speed Multiplier (from Modifier)", 8).setRange(0.001, 1000.0); declareDouble ("navi-orbit-rot-speed", "Orbital Camera Rotational Speed", 3.14 / 4).setRange(0.001, 6.28); declareDouble ("navi-orbit-speed-mult", "Orbital Camera Speed Multiplier (from Modifier)", 4).setRange(0.001, 1000.0); + declareBool ("navi-orbit-const-roll", "Keep camera roll constant for orbital camera", true); declareSeparator(); declareBool ("context-select", "Context Sensitive Selection", false); declareDouble ("drag-factor", "Mouse sensitivity during drag operations", 1.0). @@ -191,7 +192,7 @@ void CSMPrefs::State::declare() setTooltip ("Acceleration factor during drag operations while holding down shift"). setRange (0.001, 100.0); declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1); - + declareCategory ("Rendering"); declareDouble ("camera-fov", "Camera FOV", 90.).setPrecision(5).setRange(10.0, 160.0); declareBool ("camera-ortho", "Orthographic projection for camera", false); diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index abf68ef93..ca80ed34f 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -668,18 +668,25 @@ namespace CSVRender mInitialized = true; } + + void OrbitCameraController::setConstRoll(bool enabled) + { + mConstRoll = enabled; + } void OrbitCameraController::rotateHorizontal(double value) { osg::Vec3d eye, center, up; getCamera()->getViewMatrixAsLookAt(eye, center, up); - osg::Vec3 absoluteUp = osg::Vec3(0,0,1); + osg::Vec3d absoluteUp = osg::Vec3(0,0,1); - osg::Quat rotation = osg::Quat(value, absoluteUp); + osg::Quat rotation = osg::Quat(value, mConstRoll ? absoluteUp : up); osg::Vec3d oldOffset = eye - mCenter; osg::Vec3d newOffset = rotation * oldOffset; - up = rotation * up; + if (mConstRoll) + up = rotation * up; + getCamera()->setViewMatrixAsLookAt(mCenter + newOffset, mCenter, up); } @@ -687,16 +694,22 @@ namespace CSVRender { osg::Vec3d eye, center, up; getCamera()->getViewMatrixAsLookAt(eye, center, up); - osg::Vec3 absoluteUp = osg::Vec3(0,0,1); + osg::Vec3d absoluteUp = osg::Vec3(0,0,1); osg::Vec3d forward = center - eye; - osg::Vec3d axis = absoluteUp ^ forward * (up.z() < 0.0 ? -1.0 : 1.0); + osg::Vec3d axis = absoluteUp ^ forward; + + if (mConstRoll && up.z() < 0.0) + axis *= -1.0; + osg::Quat rotation = osg::Quat(value,axis); osg::Vec3d oldOffset = eye - mCenter; osg::Vec3d newOffset = rotation * oldOffset; + + if (mConstRoll) + up = rotation * up; - up = rotation * up; getCamera()->setViewMatrixAsLookAt(mCenter + newOffset, mCenter, up); } diff --git a/apps/opencs/view/render/cameracontroller.hpp b/apps/opencs/view/render/cameracontroller.hpp index a2ebba51a..658e572c5 100644 --- a/apps/opencs/view/render/cameracontroller.hpp +++ b/apps/opencs/view/render/cameracontroller.hpp @@ -160,6 +160,8 @@ namespace CSVRender /// \brief Flag controller to be re-initialized. void reset(); + void setConstRoll(bool enable); + private: void initialize(); @@ -181,6 +183,8 @@ namespace CSVRender double mOrbitSpeed; double mOrbitSpeedMult; + bool mConstRoll; + private slots: void naviPrimary(bool active); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index a151c638e..a67a38eb3 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -56,6 +56,7 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f) traits->vsync = false; mView = new osgViewer::View; + updateCameraParameters( traits->width / static_cast(traits->height) ); osg::ref_ptr window = new osgQt::GraphicsWindowQt(traits.get()); QLayout* layout = new QHBoxLayout(this); @@ -67,8 +68,6 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f) mView->getCamera()->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) ); mView->getCamera()->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); - updateCameraParameters(); - SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager; lightMgr->setStartLight(1); lightMgr->setLightingMask(Mask_Lighting); @@ -189,6 +188,8 @@ SceneWidget::SceneWidget(std::shared_ptr resourceSyste mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain); + mOrbitCamControl->setConstRoll( CSMPrefs::get()["3D Scene Input"]["navi-orbit-const-roll"].isTrue() ); + // we handle lighting manually mView->setLightingMode(osgViewer::View::NO_LIGHT); @@ -371,6 +372,10 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting) { mOrbitCamControl->setOrbitSpeedMultiplier(setting->toDouble()); } + else if (*setting=="3D Scene Input/navi-orbit-const-roll") + { + mOrbitCamControl->setConstRoll(setting->isTrue()); + } else if (*setting=="Rendering/camera-fov" || *setting=="Rendering/camera-ortho" || *setting=="Rendering/camera-ortho-size") @@ -379,7 +384,7 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting) } } -void RenderWidget::updateCameraParameters() +void RenderWidget::updateCameraParameters(double overrideAspect) { const float near = 1.0; const float far = 1000.0; @@ -387,8 +392,9 @@ void RenderWidget::updateCameraParameters() if (CSMPrefs::get()["Rendering"]["camera-ortho"].isTrue()) { const float size = CSMPrefs::get()["Rendering"]["camera-ortho-size"].toDouble(); - const float half_w = size / 100.0 * static_cast(width()); - const float half_h = size / 100.0 * static_cast(height()); + const float aspect = overrideAspect >= 0.0 ? overrideAspect : (width() / static_cast(height())); + const float half_h = size * 10.0; + const float half_w = half_h * aspect; mView->getCamera()->setProjectionMatrixAsOrtho( -half_w, half_w, -half_h, half_h, near, far); diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index af7a6f1ec..13a109a9b 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -64,7 +64,7 @@ namespace CSVRender osg::ref_ptr mView; osg::ref_ptr mRootNode; - void updateCameraParameters(); + void updateCameraParameters(double overrideAspect = -1.0); QTimer mTimer; From e309dfd234526bb4d3dc0ed9df0b18a08ca64a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 8 Dec 2017 22:06:03 +0100 Subject: [PATCH 09/24] CS: Rename variables (AppVeyor fix) --- apps/opencs/view/render/scenewidget.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index a67a38eb3..ecf27e04d 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -386,25 +386,25 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting) void RenderWidget::updateCameraParameters(double overrideAspect) { - const float near = 1.0; - const float far = 1000.0; + const float nearDist = 1.0; + const float farDist = 1000.0; if (CSMPrefs::get()["Rendering"]["camera-ortho"].isTrue()) { const float size = CSMPrefs::get()["Rendering"]["camera-ortho-size"].toDouble(); const float aspect = overrideAspect >= 0.0 ? overrideAspect : (width() / static_cast(height())); - const float half_h = size * 10.0; - const float half_w = half_h * aspect; + const float halfH = size * 10.0; + const float halfW = halfH * aspect; mView->getCamera()->setProjectionMatrixAsOrtho( - -half_w, half_w, -half_h, half_h, near, far); + -halfW, halfW, -halfH, halfH, nearDist, farDist); } else { mView->getCamera()->setProjectionMatrixAsPerspective( CSMPrefs::get()["Rendering"]["camera-fov"].toDouble(), static_cast(width())/static_cast(height()), - near, far); + nearDist, farDist); } } From 06ae61479a95fbad45ff38c4ef3f62e7988c5cbb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 8 Dec 2017 22:10:09 -0800 Subject: [PATCH 10/24] If a sound effect fails to load, substitute silence. --- apps/openmw/mwsound/openal_output.cpp | 35 ++++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 009c019e7..89475ea48 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -948,35 +948,42 @@ std::pair OpenAL_Output::loadSound(const std::string &fname DecoderPtr decoder = mManager.getDecoder(); // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. + bool succeeded; if(decoder->mResourceMgr->exists(fname)) - { - if(!decoder->open(fname)) - return std::make_pair(nullptr, 0); - } + succeeded = decoder->open(fname); else { std::string file = fname; std::string::size_type pos = file.rfind('.'); if(pos != std::string::npos) file = file.substr(0, pos)+".mp3"; - if(!decoder->open(file)) - return std::make_pair(nullptr, 0); + succeeded = decoder->open(file); } std::vector data; - ChannelConfig chans; - SampleType type; ALenum format; int srate; - if(!decoder->getInfo(&srate, &chans, &type)) - return std::make_pair(nullptr, 0); - format = getALFormat(chans, type); - if(!format) return std::make_pair(nullptr, 0); - - decoder->readAll(data); + if(succeeded) + { + ChannelConfig chans; + SampleType type; + if(decoder->getInfo(&srate, &chans, &type)) + { + format = getALFormat(chans, type); + if(format) decoder->readAll(data); + } + } decoder->close(); + if(data.empty()) + { + // If we failed to get any usable audio, substitute with silence. + format = AL_FORMAT_MONO8; + srate = 8000; + data.assign(8000, -128); + } + ALint size; ALuint buf = 0; alGenBuffers(1, &buf); From 08e947319a99021eaa3d16813c97905644a71cbf Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 9 Dec 2017 11:00:56 -0800 Subject: [PATCH 11/24] Restore exception throwing to the decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 48 ++++++++------------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 4 +- apps/openmw/mwsound/movieaudiofactory.cpp | 21 ++++----- apps/openmw/mwsound/openal_output.cpp | 52 ++++++++++++----------- apps/openmw/mwsound/sound_decoder.hpp | 4 +- 5 files changed, 56 insertions(+), 73 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 12ea84a42..e2d54876f 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -176,16 +176,16 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length) return dec; } -bool FFmpeg_Decoder::open(const std::string &fname) +void FFmpeg_Decoder::open(const std::string &fname) { close(); - try - { - mDataStream = mResourceMgr->get(fname); + mDataStream = mResourceMgr->get(fname); - if((mFormatCtx=avformat_alloc_context()) == NULL) - throw std::runtime_error("Failed to allocate context"); + if((mFormatCtx=avformat_alloc_context()) == NULL) + throw std::runtime_error("Failed to allocate context"); + try + { mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) { @@ -250,16 +250,8 @@ bool FFmpeg_Decoder::open(const std::string &fname) mOutputChannelLayout = (*mStream)->codec->channel_layout; if(mOutputChannelLayout == 0) mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels); - - return true; - } - catch(std::exception &e) - { - std::cerr<< "Could not open audio file: "<codec); mStream = NULL; @@ -273,8 +265,8 @@ bool FFmpeg_Decoder::open(const std::string &fname) mFormatCtx->pb = NULL; avformat_close_input(&mFormatCtx); + throw; } - return false; } void FFmpeg_Decoder::close() @@ -316,13 +308,10 @@ std::string FFmpeg_Decoder::getName() return mFormatCtx->filename; } -bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { if(!mStream) - { - std::cerr<< "No audio stream info" < &output) override; diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 188514f85..497562516 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -27,10 +27,10 @@ namespace MWSound private: MWSound::MovieAudioDecoder* mDecoder; - bool open(const std::string &fname) override; + void open(const std::string &fname) override; void close() override; std::string getName() override; - bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; + void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; size_t read(char *buffer, size_t bytes) override; size_t getSampleOffset() override; }; @@ -98,9 +98,9 @@ namespace MWSound }; - bool MWSoundDecoderBridge::open(const std::string &fname) + void MWSoundDecoderBridge::open(const std::string &fname) { - return false; + throw std::runtime_error("Method not implemented"); } void MWSoundDecoderBridge::close() {} @@ -109,7 +109,7 @@ namespace MWSound return mDecoder->getStreamName(); } - bool MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) + void MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { *samplerate = mDecoder->getOutputSampleRate(); @@ -125,10 +125,8 @@ namespace MWSound else if (outputChannelLayout == AV_CH_LAYOUT_QUAD) *chans = ChannelConfig_Quad; else - { - std::cerr<< "Unsupported channel layout: "<getOutputSampleFormat(); if (outputSampleFormat == AV_SAMPLE_FMT_U8) @@ -141,11 +139,8 @@ namespace MWSound { char str[1024]; av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat); - std::cerr<< "Unsupported sample format: "<getInfo(&mSampleRate, &chans, &type)) + try { + mDecoder->getInfo(&mSampleRate, &chans, &type); + mFormat = getALFormat(chans, type); + } + catch(std::exception &e) { + std::cerr<< "Failed to get stream info: "< OpenAL_Output::loadSound(const std::string &fname { getALError(); - DecoderPtr decoder = mManager.getDecoder(); - // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. - bool succeeded; - if(decoder->mResourceMgr->exists(fname)) - succeeded = decoder->open(fname); - else - { - std::string file = fname; - std::string::size_type pos = file.rfind('.'); - if(pos != std::string::npos) - file = file.substr(0, pos)+".mp3"; - succeeded = decoder->open(file); - } - std::vector data; ALenum format; int srate; - if(succeeded) - { - ChannelConfig chans; - SampleType type; - if(decoder->getInfo(&srate, &chans, &type)) + try { + DecoderPtr decoder = mManager.getDecoder(); + // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. + if(decoder->mResourceMgr->exists(fname)) + decoder->open(fname); + else { - format = getALFormat(chans, type); - if(format) decoder->readAll(data); + std::string file = fname; + std::string::size_type pos = file.rfind('.'); + if(pos != std::string::npos) + file = file.substr(0, pos)+".mp3"; + decoder->open(file); } + + ChannelConfig chans; + SampleType type; + decoder->getInfo(&srate, &chans, &type); + format = getALFormat(chans, type); + if(format) decoder->readAll(data); + } + catch(std::exception &e) { + std::cerr<< "Failed to load audio from "<close(); if(data.empty()) { diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 57edb1393..34bae87d7 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -34,11 +34,11 @@ namespace MWSound { const VFS::Manager* mResourceMgr; - virtual bool open(const std::string &fname) = 0; + virtual void open(const std::string &fname) = 0; virtual void close() = 0; virtual std::string getName() = 0; - virtual bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; + virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; virtual size_t read(char *buffer, size_t bytes) = 0; virtual void readAll(std::vector &output); From c908ad2fba38a7260f41d480ad26343622f13ae1 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 10 Dec 2017 14:38:02 +0400 Subject: [PATCH 12/24] Do not allow to place actors underground via SetPos (bug #3783) --- apps/openmw/mwscript/transformationextensions.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index c876d4cf7..208a1f46f 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -227,6 +227,17 @@ namespace MWScript } else if(axis == "z") { + // We should not place actors under ground + if (ptr.getClass().isActor()) + { + float terrainHeight = -std::numeric_limits::max(); + if (ptr.getCell()->isExterior()) + terrainHeight = MWBase::Environment::get().getWorld()->getTerrainHeightAt(osg::Vec3f(ax, ay, az)); + + if (pos < terrainHeight) + pos = terrainHeight; + } + updated = MWBase::Environment::get().getWorld()->moveObject(ptr,ax,ay,pos); } else From 0e04a26ef6d3a5453f69073d9f3351a0cd2b5c34 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 10 Dec 2017 16:10:44 +0400 Subject: [PATCH 13/24] Set duration of magic effects from ingredients (bug #4261) --- apps/openmw/mwmechanics/spellcasting.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 8fbf67535..d864dc619 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -968,9 +968,9 @@ namespace MWMechanics float y = roll / std::min(x, 100.f); y *= 0.25f * x; if (magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) - effect.mDuration = static_cast(y); - else effect.mDuration = 1; + else + effect.mDuration = static_cast(y); if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) { if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) From ba46473038f68e6e0c1a0235b518e293668d9bfa Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 13 Dec 2017 10:53:23 +0400 Subject: [PATCH 14/24] Do not skip weather transitions from SetPos script command (bug #3603) --- apps/openmw/mwscript/transformationextensions.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 208a1f46f..68b1063e4 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -202,11 +202,6 @@ namespace MWScript if (!ptr.isInCell()) return; - if (ptr == MWMechanics::getPlayer()) - { - MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); - } - std::string axis = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); Interpreter::Type_Float pos = runtime[0].mFloat; @@ -216,6 +211,8 @@ namespace MWScript float ay = ptr.getRefData().getPosition().pos[1]; float az = ptr.getRefData().getPosition().pos[2]; + // Note: SetPos does not skip weather transitions in vanilla engine, so we do not call setTeleported(true) here. + MWWorld::Ptr updated = ptr; if(axis == "x") { From 269c3227eaca6cf4a2a647e3f3f281950b09d853 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Wed, 13 Dec 2017 10:44:06 +0000 Subject: [PATCH 15/24] Make sure we have cmake for the before_install step --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d173ef6f2..02cc7cf20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ addons: - llvm-toolchain-precise-3.6 packages: [ # Dev - clang-3.6, libunshield-dev, libtinyxml-dev, + cmake, clang-3.6, libunshield-dev, libtinyxml-dev, # Tests libgtest-dev, google-mock, # Boost From b246580c6389bfe2786804ff454884b3e426e929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Wed, 13 Dec 2017 20:08:38 +0100 Subject: [PATCH 16/24] Fix orbit camera axis --- apps/opencs/view/render/cameracontroller.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index ca80ed34f..57032f5ad 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -697,11 +697,7 @@ namespace CSVRender osg::Vec3d absoluteUp = osg::Vec3(0,0,1); osg::Vec3d forward = center - eye; - - osg::Vec3d axis = absoluteUp ^ forward; - - if (mConstRoll && up.z() < 0.0) - axis *= -1.0; + osg::Vec3d axis = up ^ forward; osg::Quat rotation = osg::Quat(value,axis); osg::Vec3d oldOffset = eye - mCenter; From 79527b746a9e80fb59e73e3507fa69aad9e5b6af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 14 Dec 2017 17:29:24 +0100 Subject: [PATCH 17/24] Remove unused variable --- apps/opencs/view/render/cameracontroller.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index 57032f5ad..37f439fd3 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -694,7 +694,6 @@ namespace CSVRender { osg::Vec3d eye, center, up; getCamera()->getViewMatrixAsLookAt(eye, center, up); - osg::Vec3d absoluteUp = osg::Vec3(0,0,1); osg::Vec3d forward = center - eye; osg::Vec3d axis = up ^ forward; From f2777f72424bdd2318f88f0ef184635d629fb23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 15 Dec 2017 14:36:12 +0100 Subject: [PATCH 18/24] CS: Mover object-marker-alpha under Rendering --- apps/opencs/model/prefs/state.cpp | 2 +- apps/opencs/view/render/object.cpp | 2 +- apps/opencs/view/render/worldspacewidget.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 509d977c4..311615aec 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -192,12 +192,12 @@ void CSMPrefs::State::declare() setTooltip ("Acceleration factor during drag operations while holding down shift"). setRange (0.001, 100.0); declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1); - declareDouble ("object-marker-alpha", "Object Marker Transparency", 0.5).setPrecision(2).setRange(0,1); declareCategory ("Rendering"); declareDouble ("camera-fov", "Camera FOV", 90.).setPrecision(5).setRange(10.0, 160.0); declareBool ("camera-ortho", "Orthographic projection for camera", false); declareDouble ("camera-ortho-size", "Orthographic projection size parameter", 100.0).setPrecision(5).setRange(0.0, 1000.0); + declareDouble ("object-marker-alpha", "Object Marker Transparency", 0.5).setPrecision(2).setRange(0,1); declareCategory ("Tooltips"); declareBool ("scene", "Show Tooltips in 3D scenes", true); diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index df7283b1a..dae6467c5 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -471,7 +471,7 @@ void CSVRender::Object::setSelected(bool selected) else mRootNode->addChild(mBaseNode); - mMarkerTransparency = CSMPrefs::get()["3D Scene Input"]["object-marker-alpha"].toDouble(); + mMarkerTransparency = CSMPrefs::get()["Rendering"]["object-marker-alpha"].toDouble(); updateMarker(); } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index a80a61a79..af53c86f0 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -131,7 +131,7 @@ void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setti mDragWheelFactor = setting->toDouble(); else if (*setting=="3D Scene Input/drag-shift-factor") mDragShiftFactor = setting->toDouble(); - else if (*setting=="3D Scene Input/object-marker-alpha" && !mInConstructor) + else if (*setting=="Rendering/object-marker-alpha" && !mInConstructor) { float alpha = setting->toDouble(); // getSelection is virtual, thus this can not be called from the constructor From 1f5feeddb98e4f1c280bc306f839b539afdb925a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 15 Dec 2017 14:46:23 +0100 Subject: [PATCH 19/24] CS: Change camera parameter types to int --- apps/opencs/model/prefs/state.cpp | 4 ++-- apps/opencs/view/render/scenewidget.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 311615aec..7dfd3543b 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -194,9 +194,9 @@ void CSMPrefs::State::declare() declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1); declareCategory ("Rendering"); - declareDouble ("camera-fov", "Camera FOV", 90.).setPrecision(5).setRange(10.0, 160.0); + declareInt ("camera-fov", "Camera FOV", 90).setRange(10, 170); declareBool ("camera-ortho", "Orthographic projection for camera", false); - declareDouble ("camera-ortho-size", "Orthographic projection size parameter", 100.0).setPrecision(5).setRange(0.0, 1000.0); + declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).setRange(10, 10000); declareDouble ("object-marker-alpha", "Object Marker Transparency", 0.5).setPrecision(2).setRange(0,1); declareCategory ("Tooltips"); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index ecf27e04d..f24a9de50 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -391,7 +391,7 @@ void RenderWidget::updateCameraParameters(double overrideAspect) if (CSMPrefs::get()["Rendering"]["camera-ortho"].isTrue()) { - const float size = CSMPrefs::get()["Rendering"]["camera-ortho-size"].toDouble(); + const float size = CSMPrefs::get()["Rendering"]["camera-ortho-size"].toInt(); const float aspect = overrideAspect >= 0.0 ? overrideAspect : (width() / static_cast(height())); const float halfH = size * 10.0; const float halfW = halfH * aspect; @@ -402,7 +402,7 @@ void RenderWidget::updateCameraParameters(double overrideAspect) else { mView->getCamera()->setProjectionMatrixAsPerspective( - CSMPrefs::get()["Rendering"]["camera-fov"].toDouble(), + CSMPrefs::get()["Rendering"]["camera-fov"].toInt(), static_cast(width())/static_cast(height()), nearDist, farDist); } From 13dc1bd41e03c48555624e2f525a98ae56bdda66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 15 Dec 2017 14:56:03 +0100 Subject: [PATCH 20/24] CS: Add tooltip to camera-ortho-size preference --- apps/opencs/model/prefs/state.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 7dfd3543b..34519dcab 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -196,7 +196,9 @@ void CSMPrefs::State::declare() declareCategory ("Rendering"); declareInt ("camera-fov", "Camera FOV", 90).setRange(10, 170); declareBool ("camera-ortho", "Orthographic projection for camera", false); - declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).setRange(10, 10000); + declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100). + setTooltip("Size of the orthographic frustum, greater value will allow the camera to see more of the world."). + setRange(10, 10000); declareDouble ("object-marker-alpha", "Object Marker Transparency", 0.5).setPrecision(2).setRange(0,1); declareCategory ("Tooltips"); From 01f9d90315877930d6ec16a936a07bd122d8feed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 15 Dec 2017 17:22:32 +0100 Subject: [PATCH 21/24] CS: Reorder 3D input menu --- apps/opencs/model/prefs/state.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 34519dcab..8a9dad7f3 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -169,19 +169,25 @@ void CSMPrefs::State::declare() "list go to the first/last item"); declareCategory ("3D Scene Input"); + + declareDouble ("navi-wheel-factor", "Camera Zoom Sensitivity", 8).setRange(-100.0, 100.0); + declareDouble ("s-navi-sensitivity", "Secondary Camera Movement Sensitivity", 50.0).setRange(-1000.0, 1000.0); + declareSeparator(); + declareDouble ("p-navi-free-sensitivity", "Free Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0); declareBool ("p-navi-free-invert", "Invert Free Camera Mouse Input", false); - declareDouble ("p-navi-orbit-sensitivity", "Orbit Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0); - declareBool ("p-navi-orbit-invert", "Invert Orbit Camera Mouse Input", false); - declareDouble ("s-navi-sensitivity", "Secondary Camera Movement Sensitivity", 50.0).setRange(-1000.0, 1000.0); - declareDouble ("navi-wheel-factor", "Camera Zoom Sensitivity", 8).setRange(-100.0, 100.0); declareDouble ("navi-free-lin-speed", "Free Camera Linear Speed", 1000.0).setRange(1.0, 10000.0); - declareDouble ("navi-free-rot-speed", "Free Camera Rotational Speed", 3.14 / 2).setRange(0.001, 6.28); + declareDouble ("navi-free-rot-speed", "Free Camera Rotational Speed", 3.14 / 2).setRange(0.001, 6.28); declareDouble ("navi-free-speed-mult", "Free Camera Speed Multiplier (from Modifier)", 8).setRange(0.001, 1000.0); + declareSeparator(); + + declareDouble ("p-navi-orbit-sensitivity", "Orbit Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0); + declareBool ("p-navi-orbit-invert", "Invert Orbit Camera Mouse Input", false); declareDouble ("navi-orbit-rot-speed", "Orbital Camera Rotational Speed", 3.14 / 4).setRange(0.001, 6.28); declareDouble ("navi-orbit-speed-mult", "Orbital Camera Speed Multiplier (from Modifier)", 4).setRange(0.001, 1000.0); declareBool ("navi-orbit-const-roll", "Keep camera roll constant for orbital camera", true); declareSeparator(); + declareBool ("context-select", "Context Sensitive Selection", false); declareDouble ("drag-factor", "Mouse sensitivity during drag operations", 1.0). setRange (0.001, 100.0); From e4a1b6b5b891d3f98a7ebbadc332638d8795499e Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sat, 16 Dec 2017 14:36:27 -0600 Subject: [PATCH 22/24] Explicitly setting CMAKE_CXX_STANDARD to C++11 --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1593dda2b..1fc9f5016 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -338,6 +338,7 @@ if (NOT WIN32 AND NOT APPLE) endif() # CXX Compiler settings +set(CMAKE_CXX_STANDARD 11) if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -std=c++11 -pedantic -Wno-long-long") add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS=ON ) From 1a58171e86b90d1498808facfc955d35288730eb Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 17 Dec 2017 18:09:25 +0400 Subject: [PATCH 23/24] Do not allow to sell items from containers with zero capacity (bug #4268) --- apps/openmw/mwworld/worldimp.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 2d38f1518..340876759 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2446,9 +2446,8 @@ namespace MWWorld if (ptr.getRefData().isDeleted()) return true; - // we should not sell ingrediends from owned organic containers - MWWorld::LiveCellRef* ref = ptr.get(); - if (ref && (ref->mBase->mFlags & ESM::Container::Organic)) + // vanilla Morrowind does not allow to sell items from containers with zero capacity + if (ptr.getClass().getCapacity(ptr) <= 0.f) return true; if (Misc::StringUtils::ciEqual(ptr.getCellRef().getOwner(), mOwner.getCellRef().getRefId())) From b8c25e6bff7ae42c24073523473c0f7f47034a70 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Thu, 21 Dec 2017 14:49:09 +0000 Subject: [PATCH 24/24] Use the correct priority of animation sources in getStartTime (Fixes #4263) --- apps/openmw/mwrender/animation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a1aa24871..16ce9b436 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -625,7 +625,7 @@ namespace MWRender float Animation::getStartTime(const std::string &groupname) const { - for(AnimSourceList::const_iterator iter(mAnimSources.begin()); iter != mAnimSources.end(); ++iter) + for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter) { const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys(); @@ -638,7 +638,7 @@ namespace MWRender float Animation::getTextKeyTime(const std::string &textKey) const { - for(AnimSourceList::const_iterator iter(mAnimSources.begin()); iter != mAnimSources.end(); ++iter) + for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter) { const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();