diff --git a/CMakeLists.txt b/CMakeLists.txt index 68fdee1e8..6e0c32a22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include (OpenMWMacros) # Version set (OPENMW_VERSION_MAJOR 0) -set (OPENMW_VERSION_MINOR 16) +set (OPENMW_VERSION_MINOR 17) set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") @@ -251,13 +251,15 @@ if (APPLE) "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) endif (APPLE) +# Set up DEBUG define +set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1) # Set up Ogre plugin folder & debug suffix -# Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt) -if (DEFINED CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT APPLE) - add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") -else() +if (APPLE) + # Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt) add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="") +else () + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") endif() add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}") diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 72c5117d2..1b4ae209d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -21,7 +21,6 @@ add_openmw_dir (mwrender add_openmw_dir (mwinput inputmanagerimp - mouselookevent ) add_openmw_dir (mwgui diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 0bfd97c5d..3de4ba8ac 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -356,6 +356,8 @@ void OMW::Engine::go() pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; pos.pos[2] = 0; + mEnvironment.getWorld()->renderPlayer(); + if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (mCellName)) { MWBase::Environment::get().getWorld()->indexToPosition (exterior->data.gridX, exterior->data.gridY, diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 8b809d399..5e97b4922 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -248,6 +248,15 @@ namespace MWBase virtual bool isSwimming(const MWWorld::Ptr &object) = 0; virtual bool isUnderwater(const ESM::Cell &cell, const Ogre::Vector3 &pos) = 0; + + virtual void togglePOV() = 0; + virtual void togglePreviewMode(bool enable) = 0; + virtual bool toggleVanityMode(bool enable, bool force) = 0; + virtual void allowVanityMode(bool allow) = 0; + virtual void togglePlayerLooking(bool enable) = 0; + virtual bool isVanityEnabled() = 0; + + virtual void renderPlayer() = 0; }; } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 0c0bb74e6..177e90b95 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -49,6 +49,8 @@ namespace MWInput Ogre::RenderWindow* window = ogre.getWindow (); size_t windowHnd; + resetIdleTime(); + window->getCustomAttribute("WINDOW", &windowHnd); std::ostringstream windowHndStr; @@ -141,6 +143,8 @@ namespace MWInput if (mDragDrop) return; + resetIdleTime (); + int action = channel->getNumber(); if (currentValue == 1) { @@ -245,6 +249,46 @@ namespace MWInput mPlayer.setUpDown (-1); else mPlayer.setUpDown (0); + + if (mControlSwitch["playerviewswitch"]) { + if (actionIsActive(A_TogglePOV)) { + if (mPreviewPOVDelay <= 0.5 && + (mPreviewPOVDelay += dt) > 0.5) + { + mPreviewPOVDelay = 1.f; + MWBase::Environment::get().getWorld()->togglePreviewMode(true); + } + } else { + if (mPreviewPOVDelay > 0.5) { + //disable preview mode + MWBase::Environment::get().getWorld()->togglePreviewMode(false); + } else if (mPreviewPOVDelay > 0.f) { + MWBase::Environment::get().getWorld()->togglePOV(); + } + mPreviewPOVDelay = 0.f; + } + } + } + + if (actionIsActive(A_MoveLeft) + || actionIsActive(A_MoveRight) + || actionIsActive(A_MoveForward) + || actionIsActive(A_MoveBackward) + || actionIsActive(A_Jump) + || actionIsActive(A_Crouch)) + + { + resetIdleTime (); + } + else + { + if (mTimeIdle >= 0.f) { + mTimeIdle += dt; + } + if (mTimeIdle > 30.f && !mWindows.isGuiMode()) { + MWBase::Environment::get().getWorld()->toggleVanityMode(true, false); + mTimeIdle = -1.f; + } } } @@ -325,6 +369,14 @@ namespace MWInput mControlSwitch[sw] = value; } + void InputManager::resetIdleTime () + { + if (mTimeIdle < 0) { + MWBase::Environment::get().getWorld()->toggleVanityMode(false, false); + } + mTimeIdle = 0.f; + } + void InputManager::adjustMouseRegion(int width, int height) { const OIS::MouseState &ms = mMouse->getMouseState(); @@ -372,6 +424,8 @@ namespace MWInput { mInputCtrl->mouseMoved (arg); + resetIdleTime (); + if (mGuiCursorEnabled) { const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); @@ -539,6 +593,7 @@ namespace MWInput defaultKeyBindings[A_Journal] = OIS::KC_J; defaultKeyBindings[A_Rest] = OIS::KC_T; defaultKeyBindings[A_GameMenu] = OIS::KC_ESCAPE; + defaultKeyBindings[A_TogglePOV] = OIS::KC_TAB; std::map defaultMouseButtonBindings; defaultMouseButtonBindings[A_Inventory] = OIS::MB_Right; @@ -588,6 +643,7 @@ namespace MWInput descriptions[A_Journal] = "sJournal"; descriptions[A_Rest] = "sRestKey"; descriptions[A_Inventory] = "sInventory"; + descriptions[A_TogglePOV] = "sTogglePOVCmd"; if (descriptions[action] == "") return ""; // not configurable @@ -617,6 +673,7 @@ namespace MWInput ret.push_back(A_MoveBackward); ret.push_back(A_MoveLeft); ret.push_back(A_MoveRight); + ret.push_back(A_TogglePOV); ret.push_back(A_Crouch); ret.push_back(A_Activate); ret.push_back(A_ToggleWeapon); @@ -708,5 +765,4 @@ namespace MWInput { loadKeyDefaults(true); } - } diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index c8b48e727..71d43b8d5 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -146,6 +146,9 @@ namespace MWInput float mMouseX; float mMouseY; + float mPreviewPOVDelay; + float mTimeIdle; + std::map mControlSwitch; @@ -169,6 +172,8 @@ namespace MWInput void loadKeyDefaults(bool force = false); + void resetIdleTime(); + private: enum Actions { @@ -213,10 +218,10 @@ namespace MWInput A_ToggleWeapon, A_ToggleSpell, + A_TogglePOV, + A_Last // Marker for the last item }; - - }; } #endif diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 704a10cfe..0e85d32e0 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -290,7 +290,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni } - Vector3 playerdirection = -mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis(); + Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis(); Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z); diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 94a3f71c8..8b99e001a 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -4,104 +4,359 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/refdata.hpp" +#include "npcanimation.hpp" + namespace MWRender { Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node) - : mCamera (camera), - mNode (node), + : mCamera(camera), + mPlayerNode(node), + mCameraNode(mPlayerNode->createChildSceneNode()), mFirstPersonView(true), - mVanityModeEnabled(false) - {} + mPreviewMode(false), + mFreeLook(true), + mHeight(128.f), + mCameraDistance(300.f), + mDistanceAdjusted(false) + { + mVanity.enabled = false; + mVanity.allowed = true; + mVanity.forced = false; - bool Player::setRotation(const Ogre::Vector3 &rot) + mCameraNode->attachObject(mCamera); + mCameraNode->setPosition(0.f, 0.f, mHeight); + + mPreviewCam.yaw = 0.f; + mPreviewCam.offset = 400.f; + } + + bool Player::rotate(const Ogre::Vector3 &rot, bool adjust) { - Ogre::SceneNode *sceneNode = mNode; - Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); - Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); + if (mVanity.enabled) { + toggleVanityMode(false); + } + + Ogre::Vector3 trueRot = rot; + + /// \note rotate player on forced vanity + if (mVanity.forced) { + if (mFreeLook) { + float diff = (adjust) ? rot.z : mMainCam.yaw - rot.z; - // we are only interested in X and Y rotation + mVanity.enabled = false; + rotateCamera(rot, adjust); + mVanity.enabled = true; - // Rotate around X axis - Ogre::Radian radx(rot.x); - if (radx.valueDegrees() > 89.5f) { - radx = Ogre::Degree(89.5f); - } else if (radx.valueDegrees() < -89.5f) { - radx = Ogre::Degree(-89.5f); + compensateYaw(diff); + } + trueRot.z = 0.f; } - Ogre::Quaternion xr(radx, Ogre::Vector3::UNIT_X); - // Rotate around Y axis - Ogre::Quaternion yr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Y); + if (mFreeLook || mVanity.enabled || mPreviewMode) { + rotateCamera(trueRot, adjust); + } - pitchNode->setOrientation(xr); - yawNode->setOrientation(yr); + /// \note if vanity mode is forced by TVM then rotate player + return (!mVanity.enabled && !mPreviewMode) || mVanity.forced; + } + void Player::rotateCamera(const Ogre::Vector3 &rot, bool adjust) + { + if (adjust) { + setYaw(getYaw() + rot.z); + setPitch(getPitch() + rot.x); + } else { + setYaw(rot.z); + setPitch(rot.x); + } + Ogre::Quaternion xr( + Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), + Ogre::Vector3::UNIT_X + ); + Ogre::Quaternion zr( + Ogre::Radian(getYaw()), + Ogre::Vector3::NEGATIVE_UNIT_Z + ); + if (!mVanity.enabled && !mPreviewMode) { + mPlayerNode->setOrientation(zr); + mCameraNode->setOrientation(xr); + } else { + mCameraNode->setOrientation(zr * xr); + } updateListener(); - - return !mVanityModeEnabled; } std::string Player::getHandle() const { - return mNode->getName(); + return mPlayerNode->getName(); } void Player::attachTo(const MWWorld::Ptr &ptr) { - ptr.getRefData().setBaseNode(mNode); + ptr.getRefData().setBaseNode(mPlayerNode); + } + + void Player::updateListener() + { + Ogre::Vector3 pos = mCamera->getRealPosition(); + Ogre::Vector3 dir = mCamera->getRealDirection(); + + Ogre::Real xch; + xch = pos.y, pos.y = -pos.z, pos.z = xch; + xch = dir.y, dir.y = -dir.z, dir.z = xch; + + MWBase::Environment::get().getSoundManager()->setListenerPosDir(pos, dir); + } + + void Player::update(float duration) + { + if (mAnimation) { + mAnimation->runAnimation(duration); + } + if (mFirstPersonView && !mVanity.enabled) { + return; + } + if (mVanity.enabled) { + Ogre::Vector3 rot(0.f, 0.f, 0.f); + rot.z = Ogre::Degree(3.f * duration).valueRadians(); + rotateCamera(rot, true); + } } - bool Player::adjustRotation(const Ogre::Vector3 &rot) + void Player::toggleViewMode() { - Ogre::SceneNode *pitchNode = mCamera->getParentSceneNode(); - Ogre::SceneNode *yawNode = pitchNode->getParentSceneNode(); + mFirstPersonView = !mFirstPersonView; + if (mFirstPersonView) { + mCamera->setPosition(0.f, 0.f, 0.f); + setLowHeight(false); + } else { + mCamera->setPosition(0.f, 0.f, mCameraDistance); + setLowHeight(true); + } + mPlayerNode->setVisible(!mFirstPersonView, false); + } + + void Player::allowVanityMode(bool allow) + { + if (!allow && mVanity.enabled && !mVanity.forced) { + toggleVanityMode(false); + } + mVanity.allowed = allow; + } - float f = controlFlip(Ogre::Radian(rot.x).valueDegrees()); - if (f != 0.0) { - pitchNode->pitch(Ogre::Degree(f)); + bool Player::toggleVanityMode(bool enable, bool force) + { + if ((mVanity.forced && !force) || + (!mVanity.allowed && (force || enable))) + { + return false; + } else if (mVanity.enabled == enable) { + return true; } - yawNode->yaw(Ogre::Radian(-rot.z)); + mVanity.enabled = enable; + mVanity.forced = force && enable; - updateListener(); + float offset = mPreviewCam.offset; + Ogre::Vector3 rot(0.f, 0.f, 0.f); + if (mVanity.enabled) { + rot.x = Ogre::Degree(-30.f).valueRadians(); + mMainCam.offset = mCamera->getPosition().z; + + mPlayerNode->setVisible(true, false); + setLowHeight(true); + } else { + rot.x = getPitch(); + offset = mMainCam.offset; - return !mVanityModeEnabled; + mPlayerNode->setVisible(!mFirstPersonView, false); + setLowHeight(!mFirstPersonView); + } + rot.z = getYaw(); + mCamera->setPosition(0.f, 0.f, offset); + rotateCamera(rot, false); + + return true; } - float Player::controlFlip(float shift) + void Player::togglePreviewMode(bool enable) { - Ogre::SceneNode *pitchNode = mCamera->getParentSceneNode(); - Ogre::Quaternion orient = pitchNode->getOrientation(); + if (mPreviewMode == enable) { + return; + } + mPreviewMode = enable; + float offset = mCamera->getPosition().z; + if (mPreviewMode) { + mMainCam.offset = offset; + offset = mPreviewCam.offset; - float pitchAngle = - (2 * Ogre::Degree(Ogre::Math::ASin(orient.x)).valueDegrees()); + mPlayerNode->setVisible(true, false); + setLowHeight(true); + } else { + mPreviewCam.offset = offset; + offset = mMainCam.offset; - if (pitchAngle + shift < 89.5f && pitchAngle + shift > -89.5f) { - return shift; + mPlayerNode->setVisible(!mFirstPersonView, false); + setLowHeight(!mFirstPersonView); } - if (pitchAngle > 0) { - float f = 89.5f - pitchAngle - shift; - return (f > 0.f) ? f : 0.f; - } else if (pitchAngle < 0) { - float f = -89.5 - pitchAngle - shift; - return (f < 0.f) ? f : 0.f; + mCamera->setPosition(0.f, 0.f, offset); + rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); + } + + float Player::getYaw() + { + if (mVanity.enabled || mPreviewMode) { + return mPreviewCam.yaw; } - return 0.f; + return mMainCam.yaw; } - void Player::updateListener() + void Player::setYaw(float angle) { - Ogre::Vector3 pos = mCamera->getRealPosition(); - Ogre::Vector3 dir = mCamera->getRealDirection(); + if (angle > Ogre::Math::PI) { + angle -= Ogre::Math::TWO_PI; + } else if (angle < -Ogre::Math::PI) { + angle += Ogre::Math::TWO_PI; + } + if (mVanity.enabled || mPreviewMode) { + mPreviewCam.yaw = angle; + } else { + mMainCam.yaw = angle; + } + } - Ogre::Real xch; - xch = pos.y, pos.y = -pos.z, pos.z = xch; - xch = dir.y, dir.y = -dir.z, dir.z = xch; + float Player::getPitch() + { + if (mVanity.enabled || mPreviewMode) { + return mPreviewCam.pitch; + } + return mMainCam.pitch; + } - MWBase::Environment::get().getSoundManager()->setListenerPosDir(pos, dir); + void Player::setPitch(float angle) + { + float limit = Ogre::Math::HALF_PI; + if (mVanity.forced || mPreviewMode) { + limit /= 2; + } + if (angle > limit) { + angle = limit - 0.01; + } else if (angle < -limit) { + angle = -limit + 0.01; + } + if (mVanity.enabled || mPreviewMode) { + mPreviewCam.pitch = angle; + } else { + mMainCam.pitch = angle; + } + } + + void Player::setCameraDistance(float dist, bool adjust, bool override) + { + if (mFirstPersonView && !mPreviewMode && !mVanity.enabled) { + return; + } + Ogre::Vector3 v(0.f, 0.f, dist); + if (adjust) { + v += mCamera->getPosition(); + } + if (v.z > 800.f) { + v.z = 800.f; + } else if (v.z < 10.f) { + v.z = 10.f; + } + mCamera->setPosition(v); + + if (override) { + if (mVanity.enabled || mPreviewMode) { + mPreviewCam.offset = v.z; + } else if (!mFirstPersonView) { + mCameraDistance = v.z; + } + } else { + mDistanceAdjusted = true; + } + } + + void Player::setCameraDistance() + { + if (mDistanceAdjusted) { + if (mVanity.enabled || mPreviewMode) { + mCamera->setPosition(0, 0, mPreviewCam.offset); + } else if (!mFirstPersonView) { + mCamera->setPosition(0, 0, mCameraDistance); + } + } + mDistanceAdjusted = false; + } + + void Player::setAnimation(NpcAnimation *anim) + { + mAnimation = anim; + mPlayerNode->setVisible(!mFirstPersonView, false); + } + + void Player::setHeight(float height) + { + mHeight = height; + mCameraNode->setPosition(0.f, 0.f, mHeight); + } + + float Player::getHeight() + { + return mHeight * mPlayerNode->getScale().z; + } + + bool Player::getPosition(Ogre::Vector3 &player, Ogre::Vector3 &camera) + { + float xch; + camera = mCamera->getRealPosition(); + xch = camera.z, camera.z = camera.y, camera.y = -xch; + player = mPlayerNode->getPosition(); + + return mFirstPersonView && !mVanity.enabled && !mPreviewMode; + } + + Ogre::Vector3 Player::getPosition() + { + return mPlayerNode->getPosition(); + } + + void Player::getSightAngles(float &pitch, float &yaw) + { + pitch = mMainCam.pitch; + yaw = mMainCam.yaw; + } + + void Player::compensateYaw(float diff) + { + mPreviewCam.yaw -= diff; + Ogre::Quaternion zr( + Ogre::Radian(mPreviewCam.yaw), + Ogre::Vector3::NEGATIVE_UNIT_Z + ); + Ogre::Quaternion xr( + Ogre::Radian(mPreviewCam.pitch), + Ogre::Vector3::UNIT_X); + mCameraNode->setOrientation(zr * xr); + } + + void Player::togglePlayerLooking(bool enable) + { + mFreeLook = enable; + } + + void Player::setLowHeight(bool low) + { + if (low) { + mCameraNode->setPosition(0.f, 0.f, mHeight * 0.85); + } else { + mCameraNode->setPosition(0.f, 0.f, mHeight); + } } } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index 981ecfe0b..e56abc17d 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -3,9 +3,8 @@ #include - namespace Ogre -{ +{ class Vector3; class Camera; class SceneNode; @@ -18,20 +17,49 @@ namespace MWWorld namespace MWRender { + class NpcAnimation; /// \brief Player character rendering and camera control class Player { + struct CamData { + float pitch, yaw, offset; + }; + Ogre::Camera *mCamera; - Ogre::SceneNode* mNode; + + Ogre::SceneNode *mPlayerNode; + Ogre::SceneNode *mCameraNode; + + NpcAnimation *mAnimation; bool mFirstPersonView; - bool mVanityModeEnabled; + bool mPreviewMode; + bool mFreeLook; + + struct { + bool enabled, allowed, forced; + } mVanity; + + float mHeight, mCameraDistance; + CamData mMainCam, mPreviewCam; - float controlFlip(float shift = 0.f); + bool mDistanceAdjusted; /// Updates sound manager listener data void updateListener(); + void rotateCamera(const Ogre::Vector3 &rot, bool adjust); + + float getYaw(); + void setYaw(float angle); + + float getPitch(); + void setPitch(float angle); + + void compensateYaw(float diff); + + void setLowHeight(bool low = true); + public: Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); @@ -39,11 +67,7 @@ namespace MWRender /// Set where the player is looking at. Uses Morrowind (euler) angles /// \param rot Rotation angles in radians /// \return true if player object needs to bo rotated physically - bool setRotation(const Ogre::Vector3 &rot); - - /// \param rot Rotation angles in radians - /// \return true if player object needs to bo rotated physically - bool adjustRotation(const Ogre::Vector3 &rot); + bool rotate(const Ogre::Vector3 &rot, bool adjust); std::string getHandle() const; @@ -52,12 +76,40 @@ namespace MWRender /// several different objects void attachTo(const MWWorld::Ptr &); - void toggleViewMode() { - mFirstPersonView = !mFirstPersonView; - } + void toggleViewMode(); + + bool toggleVanityMode(bool enable, bool force = false); + void allowVanityMode(bool allow); + + void togglePreviewMode(bool enable); + + void update(float duration); + + /// Set camera distance for current mode. Don't work on 1st person view. + /// \param adjust Indicates should distance be adjusted or set. + /// \param override If true new distance will be used as default. + /// If false, default distance can be restored with setCameraDistance(). + void setCameraDistance(float dist, bool adjust = false, bool override = true); + + /// Restore default camera distance for current mode. + void setCameraDistance(); + + void setAnimation(MWRender::NpcAnimation *anim); + + void setHeight(float height); + float getHeight(); + + /// Stores player and camera world positions in passed arguments + /// \return true if camera at the eye-place + bool getPosition(Ogre::Vector3 &player, Ogre::Vector3 &camera); + Ogre::Vector3 getPosition(); + + void getSightAngles(float &pitch, float &yaw); + + void togglePlayerLooking(bool enable); - void toggleVanityMode() { - mVanityModeEnabled = !mVanityModeEnabled; + bool isVanityEnabled() { + return mVanity.enabled; } }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index d0019c6b8..2d29e8f55 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -33,6 +33,7 @@ #include "localmap.hpp" #include "water.hpp" #include "compositors.hpp" +#include "npcanimation.hpp" using namespace MWRender; using namespace Ogre; @@ -40,7 +41,7 @@ using namespace Ogre; namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine) - :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0) + :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine) { // select best shader mode bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos); @@ -130,14 +131,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const SceneNode *rt = mRendering.getScene()->getRootSceneNode(); mMwRoot = rt->createChildSceneNode(); mMwRoot->pitch(Degree(-90)); + mObjects.setMwRoot(mMwRoot); mActors.setMwRoot(mMwRoot); Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player"); - playerNode->pitch(Degree(90)); - Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); - Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); - cameraPitchNode->attachObject(mRendering.getCamera()); + mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mShadows = new Shadows(&mRendering); @@ -147,7 +146,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); - mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mSun = 0; mDebugging = new Debugging(mMwRoot, engine); @@ -259,11 +257,7 @@ RenderingManager::rotateObject( bool force = true; if (isPlayer) { - if (adjust) { - force = mPlayer->adjustRotation(rot); - } else { - force = mPlayer->setRotation(rot); - } + force = mPlayer->rotate(rot, adjust); } MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z); @@ -302,7 +296,22 @@ RenderingManager::moveObjectToCell( child->setPosition(pos); } -void RenderingManager::update (float duration){ +void RenderingManager::update (float duration) +{ + Ogre::Vector3 orig, dest; + mPlayer->setCameraDistance(); + if (!mPlayer->getPosition(orig, dest)) { + orig.z += mPlayer->getHeight() * mMwRoot->getScale().z; + + btVector3 btOrig(orig.x, orig.y, orig.z); + btVector3 btDest(dest.x, dest.y, dest.z); + std::pair test = + mPhysicsEngine->rayTest(btOrig, btDest); + if (!test.first.empty()) { + mPlayer->setCameraDistance(test.second * orig.distance(dest), false, false); + } + } + mPlayer->update(duration); mActors.update (duration); mObjects.update (duration); @@ -315,7 +324,23 @@ void RenderingManager::update (float duration){ mRendering.update(duration); - mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() ); + MWWorld::RefData &data = + MWBase::Environment::get() + .getWorld() + ->getPlayer() + .getPlayer() + .getRefData(); + + float *fpos = data.getPosition().pos; + + /// \note only for LocalMap::updatePlayer() + Ogre::Vector3 pos(fpos[0], -fpos[2], -fpos[1]); + + Ogre::SceneNode *node = data.getBaseNode(); + Ogre::Quaternion orient = + node->convertLocalToWorldOrientation(node->_getDerivedOrientation()); + + mLocalMap->updatePlayer(pos, orient); if (mWater) { Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); @@ -820,4 +845,22 @@ void RenderingManager::attachCameraTo(const MWWorld::Ptr &ptr) mPlayer->attachTo(ptr); } +void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr) +{ + MWRender::NpcAnimation *anim = + new MWRender::NpcAnimation( + ptr, + mRendering, + MWWorld::Class::get(ptr).getInventoryStore(ptr) + ); + mPlayer->setAnimation(anim); +} + +void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw) +{ + eyepos = mPlayer->getPosition(); + eyepos.z += mPlayer->getHeight(); + mPlayer->getSightAngles(pitch, yaw); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index ef6f18a75..003a61a39 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -56,7 +56,34 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine); virtual ~RenderingManager(); + void togglePOV() { + mPlayer->toggleViewMode(); + } + + void togglePreviewMode(bool enable) { + mPlayer->togglePreviewMode(enable); + } + + bool toggleVanityMode(bool enable, bool force) { + return mPlayer->toggleVanityMode(enable, force); + } + + bool isVanityEnabled() { + return mPlayer->isVanityEnabled(); + } + + void allowVanityMode(bool allow) { + mPlayer->allowVanityMode(allow); + } + + void togglePlayerLooking(bool enable) { + mPlayer->togglePlayerLooking(enable); + } + + void getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw); + void attachCameraTo(const MWWorld::Ptr &ptr); + void renderPlayer(const MWWorld::Ptr &ptr); SkyManager* getSkyManager(); Compositors* getCompositors(); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 9e551ba2a..eba605d0c 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -280,7 +280,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mMoonRed(false) { mSceneMgr = pMwRoot->getCreator(); - mRootNode = mCamera->getParentSceneNode()->createChildSceneNode(); + mRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates mRootNode->setInheritOrientation(false); } @@ -405,6 +405,9 @@ void SkyManager::update(float duration) { if (!mEnabled) return; + mCamera->getParentSceneNode ()->needUpdate (); + mRootNode->setPosition(mCamera->getDerivedPosition()); + // UV Scroll the clouds mCloudAnimationTimer += duration * mCloudSpeed * (MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f); sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer", @@ -666,12 +669,13 @@ Ogre::SceneNode* SkyManager::getSunNode() void SkyManager::setSkyPosition(const Ogre::Vector3& position) { - mRootNode->_setDerivedPosition(position); + mRootNode->setPosition(position); } void SkyManager::resetSkyPosition() { - mRootNode->setPosition(0,0,0); + mCamera->getParentSceneNode ()->needUpdate (); + mRootNode->setPosition(mCamera->getDerivedPosition()); } void SkyManager::scaleSky(float scale) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index d5b93b7cb..e79f308cd 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -32,7 +32,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), mReflectionRenderActive(false), mRendering(rend), - mOldFarClip(0), mOldFarClip2(0), mWaterTimer(0.f) { mSky = rend->getSkyManager(); @@ -207,6 +206,7 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) { if (evt.source == mReflectionTarget) { + mCamera->getParentSceneNode ()->needUpdate (); mReflectionCamera->setOrientation(mCamera->getDerivedOrientation()); mReflectionCamera->setPosition(mCamera->getDerivedPosition()); mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance()); @@ -215,11 +215,9 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) mReflectionCamera->setFOVy(mCamera->getFOVy()); mReflectionRenderActive = true; - /// \todo the reflection render (and probably all renderingmanager-updates) lag behind 1 camera frame for some reason Vector3 pos = mCamera->getRealPosition(); pos.y = mTop*2 - pos.y; mSky->setSkyPosition(pos); - mSky->scaleSky(mCamera->getFarClipDistance() / 50.f); mReflectionCamera->enableReflection(mWaterPlane); } } @@ -229,7 +227,6 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) if (evt.source == mReflectionTarget) { mSky->resetSkyPosition(); - mSky->scaleSky(1); mReflectionCamera->disableReflection(); mReflectionCamera->disableCustomNearClipPlane(); mReflectionRenderActive = false; @@ -269,34 +266,19 @@ void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &in // We don't want the sky to get clipped by custom near clip plane (the water plane) if (queueGroupId < 20 && mReflectionRenderActive) { - mOldFarClip = mReflectionCamera->getFarClipDistance (); mReflectionCamera->disableCustomNearClipPlane(); - mReflectionCamera->setFarClipDistance (1000000000); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } - else if (queueGroupId == RQG_UnderWater) - {/* - mOldFarClip2 = mCamera->getFarClipDistance (); - mCamera->setFarClipDistance (1000000000); - Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); - */} } void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) { if (queueGroupId < 20 && mReflectionRenderActive) { - mReflectionCamera->setFarClipDistance (mOldFarClip); if (!mIsUnderwater) mReflectionCamera->enableCustomNearClipPlane(mErrorPlane); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } - if (queueGroupId == RQG_UnderWater) - { - /* - mCamera->setFarClipDistance (mOldFarClip2); - Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); - */} } void Water::update(float dt) diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index f56ba7410..dcb76533b 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -50,9 +50,6 @@ namespace MWRender { bool mToggled; int mTop; - int mOldFarClip; - int mOldFarClip2; - float mWaterTimer; bool mReflectionRenderActive; diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 1ea5f8e3e..dbc8159d1 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -181,4 +181,5 @@ op 0x2000170: user4, explicit reference (console only, requires --script-console op 0x2000171: user4 (implicit reference, console only, requires --script-console switch) op 0x2000172: GetStartingAngle op 0x2000173: GetStartingAngle, explicit reference -opcodes 0x2000174-0x3ffffff unused +op 0x2000174: ToggleVanityMode +opcodes 0x2000175-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 0c328e0da..e9e29bdae 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -207,6 +207,29 @@ namespace MWScript } }; + class OpToggleVanityMode : public Interpreter::Opcode0 + { + public: + + virtual void execute(Interpreter::Runtime &runtime) + { + InterpreterContext& context = + static_cast (runtime.getContext()); + + MWBase::World *world = + MWBase::Environment::get().getWorld(); + + bool value = !world->isVanityEnabled(); + if (world->toggleVanityMode(value, true)) { + context.report( + (value) ? "Vanity Mode -> On" : "Vanity Mode -> Off" + ); + } else { + context.report("Vanity Mode -> No"); + } + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -222,6 +245,7 @@ namespace MWScript const int opcodeToggleWater = 0x2000144; const int opcodeTogglePathgrid = 0x2000146; const int opcodeDontSaveObject = 0x2000153; + const int opcodeToggleVanityMode = 0x2000174; void registerExtensions (Compiler::Extensions& extensions) { @@ -244,6 +268,8 @@ namespace MWScript extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject); + extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode); + extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -263,6 +289,7 @@ namespace MWScript interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject); + interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode); } } } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 45cfdd123..b7cb2778d 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -11,7 +11,7 @@ #include -#include "../mwbase/world.hpp" // FIXME +//#include "../mwbase/world.hpp" // FIXME #include "ptr.hpp" #include "class.hpp" @@ -42,32 +42,38 @@ namespace MWWorld return mEngine; } - std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) - { - std::string handle = ""; - - //get a ray pointing to the center of the viewport - Ray centerRay = mRender.getCamera()->getCameraToViewportRay( - mRender.getViewport()->getWidth()/2, - mRender.getViewport()->getHeight()/2); - //let's avoid the capsule shape of the player. - centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); - btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); - btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); - - return mEngine->rayTest(from,to); + std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) + { + btVector3 dir(0, 1, 0); + dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); + dir = dir.rotate(btVector3(0, 0, 1), mPlayerData.yaw); + dir.setX(-dir.x()); + + btVector3 origin( + mPlayerData.eyepos.x, + mPlayerData.eyepos.y, + mPlayerData.eyepos.z); + origin += dir * 5; + + btVector3 dest = origin + dir * 500; + return mEngine->rayTest(origin, dest); } std::vector < std::pair > PhysicsSystem::getFacedObjects () { - //get a ray pointing to the center of the viewport - Ray centerRay = mRender.getCamera()->getCameraToViewportRay( - mRender.getViewport()->getWidth()/2, - mRender.getViewport()->getHeight()/2); - btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); - btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); - - return mEngine->rayTest2(from,to); + btVector3 dir(0, 1, 0); + dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); + dir = dir.rotate(btVector3(0, 0, 1), mPlayerData.yaw); + dir.setX(-dir.x()); + + btVector3 origin( + mPlayerData.eyepos.x, + mPlayerData.eyepos.y, + mPlayerData.eyepos.z); + origin += dir * 5; + + btVector3 dest = origin + dir * 500; + return mEngine->rayTest2(origin, dest); } std::vector < std::pair > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) @@ -172,7 +178,7 @@ namespace MWWorld OEngine::Physic::PhysicActor* act = it->second; act->setWalkDirection(btVector3(0,0,0)); } - playerMove::playercmd& pm_ref = playerphysics->cmd; + playerMove::playercmd& pm_ref = playerphysics->cmd; pm_ref.rightmove = 0; pm_ref.forwardmove = 0; @@ -183,35 +189,18 @@ namespace MWWorld iter!=actors.end(); ++iter) { //dirty stuff to get the camera orientation. Must be changed! + if (iter->first == "player") { + playerphysics->ps.viewangles.x = + Ogre::Radian(mPlayerData.pitch).valueDegrees(); - Ogre::SceneNode *sceneNode = mRender.getScene()->getSceneNode (iter->first); - Ogre::Vector3 dir; - Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); - Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); - Ogre::Quaternion yawQuat = yawNode->getOrientation(); - Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); - - - - playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); - - playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; - - - Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - - pm_ref.rightmove = -iter->second.x; - pm_ref.forwardmove = -iter->second.y; - pm_ref.upmove = iter->second.z; - - + playerphysics->ps.viewangles.y = + Ogre::Radian(mPlayerData.yaw).valueDegrees() + 90; + pm_ref.rightmove = -iter->second.x; + pm_ref.forwardmove = -iter->second.y; + pm_ref.upmove = iter->second.z; + } } - - - - - mEngine->stepSimulation(dt); } @@ -402,4 +391,11 @@ namespace MWWorld return true; } + + void PhysicsSystem::updatePlayerData(Ogre::Vector3 &eyepos, float pitch, float yaw) + { + mPlayerData.eyepos = eyepos; + mPlayerData.pitch = pitch; + mPlayerData.yaw = yaw; + } } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index e42fa536b..c6b8199fa 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -70,7 +70,14 @@ namespace MWWorld bool getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max); + void updatePlayerData(Ogre::Vector3 &eyepos, float pitch, float yaw); + private: + struct { + Ogre::Vector3 eyepos; + float pitch, yaw; + } mPlayerData; + OEngine::Render::OgreRenderer &mRender; OEngine::Physic::PhysicEngine* mEngine; bool mFreeFly; @@ -80,7 +87,6 @@ namespace MWWorld PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); }; - } #endif diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 8ace54378..655397c1f 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -806,6 +806,11 @@ namespace MWWorld /// \todo split this function up into subfunctions mWorldScene->update (duration); + + float pitch, yaw; + Ogre::Vector3 eyepos; + mRendering->getPlayerData(eyepos, pitch, yaw); + mPhysics->updatePlayerData(eyepos, pitch, yaw); mWeatherManager->update (duration); @@ -1152,4 +1157,8 @@ namespace MWWorld return pos.z < cell.water; } + void World::renderPlayer() + { + mRendering->renderPlayer(mPlayer->getPlayer()); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 4031a180a..889741989 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -277,6 +277,31 @@ namespace MWWorld virtual bool isSwimming(const MWWorld::Ptr &object); virtual bool isUnderwater(const ESM::Cell &cell, const Ogre::Vector3 &pos); + virtual void togglePOV() { + mRendering->togglePOV(); + } + + virtual void togglePreviewMode(bool enable) { + mRendering->togglePreviewMode(enable); + } + + virtual bool toggleVanityMode(bool enable, bool force) { + return mRendering->toggleVanityMode(enable, force); + } + + virtual void allowVanityMode(bool allow) { + mRendering->allowVanityMode(allow); + } + + virtual void togglePlayerLooking(bool enable) { + mRendering->togglePlayerLooking(enable); + } + + virtual void renderPlayer(); + + virtual bool isVanityEnabled() { + return mRendering->isVanityEnabled(); + } }; } diff --git a/components/files/ogreplugin.cpp b/components/files/ogreplugin.cpp index c434114b3..ca90fd30e 100644 --- a/components/files/ogreplugin.cpp +++ b/components/files/ogreplugin.cpp @@ -6,7 +6,11 @@ namespace Files { bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre::Root &ogreRoot) { + // Append plugin suffix if debugging. +#if defined(DEBUG) pluginName = pluginName + OGRE_PLUGIN_DEBUG_SUFFIX; +#endif + #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE std::ostringstream verStream; verStream << "." << OGRE_VERSION_MAJOR << "." << OGRE_VERSION_MINOR << "." << OGRE_VERSION_PATCH; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 4393749fb..0fdeaae3d 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -471,7 +471,7 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam float glossiness = 0.0f; float alpha = 1.0f; int alphaFlags = -1; - ubyte alphaTest = 0; +// ubyte alphaTest = 0; Ogre::String texName; bool vertexColour = (shape->data->colors.size() != 0); @@ -523,7 +523,7 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam if (a) { alphaFlags = a->flags; - alphaTest = a->data.threshold; +// alphaTest = a->data.threshold; } // Material diff --git a/credits.txt b/credits.txt index ca0ff7323..c7ec4936e 100644 --- a/credits.txt +++ b/credits.txt @@ -35,7 +35,7 @@ Sylvain T. (Garvek) Packagers: Alexander Olofsson (Ace) - Windows BrotherBrick - Ubuntu Linux -edmundo - Gentoo Linux +Edmondo Tommasina - Gentoo Linux Kenny Armstrong (artorius) - Fedora Linux Nikolay Kasyanov (corristo) - Mac OS X Sandy Carter (bwrsandman) - Arch Linux diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index 2d18aaa4d..89d654e6a 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -97,8 +97,8 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& - const btVector3 btstart(start.x, start.y, start.z); - const btVector3 btend(end.x, end.y, end.z); + const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z); + const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z); const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); diff --git a/readme.txt b/readme.txt index ce3d115e3..10a0a6f5d 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.16.0 +Version: 0.17.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org @@ -97,6 +97,37 @@ Allowed options: CHANGELOG +0.17.0 + +Bug #225: Valgrind reports about 40MB of leaked memory +Bug #241: Some physics meshes still don't match +Bug #248: Some textures are too dark +Bug #300: Dependency on proprietary CG toolkit +Bug #302: Some objects don't collide although they should +Bug #308: Freeze in Balmora, Meldor: Armorer +Bug #313: openmw without a ~/.config/openmw folder segfault. +Bug #317: adding non-existing spell via console locks game +Bug #318: Wrong character normals +Bug #341: Building with Ogre Debug libraries does not use debug version of plugins +Bug #347: Crash when running openmw with --start="XYZ" +Bug #353: FindMyGUI.cmake breaks path on Windows +Bug #359: WindowManager throws exception at destruction +Feature #33: Allow objects to cross cell-borders +Feature #59: Dropping Items (replaced stopgap implementation with a proper one) +Feature #93: Main Menu +Feature #96/329/330/331/332/333: Player Control +Feature #180: Object rotation and scaling. +Feature #272: Incorrect NIF material sharing +Feature #314: Potion usage +Feature #324: Skill Gain +Feature #342: Drain/fortify dynamic stats/attributes magic effects +Feature #350: Allow console only script instructions +Feature #352: Run scripts in console on startup +Task #107: Refactor mw*-subsystems +Task #325: Make CreatureStats into a class +Task #345: Use Ogre's animation system +Task #351: Rewrite Action class to support automatic sound playing + 0.16.0 Bug #250: OpenMW launcher erratic behaviour