diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 08033f822..b5d4badf2 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -14,7 +14,7 @@ set(GAME_HEADER source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender - renderingmanager debugging sky player animation npcanimation creatureanimation activatoranimation + renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows compositors characterpreview externalrendering globalmap videoplayer ripplesimulation refraction ) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index df91bc945..a3b9d2cf2 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -317,7 +317,7 @@ namespace MWBase virtual void togglePOV() = 0; virtual void togglePreviewMode(bool enable) = 0; - virtual bool toggleVanityMode(bool enable, bool force) = 0; + virtual bool toggleVanityMode(bool enable) = 0; virtual void allowVanityMode(bool allow) = 0; virtual void togglePlayerLooking(bool enable) = 0; virtual void changeVanityModeScale(float factor) = 0; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 882edadce..1cd716413 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -720,19 +720,17 @@ namespace MWInput void InputManager::resetIdleTime() { - if (mTimeIdle < 0) { - MWBase::Environment::get().getWorld()->toggleVanityMode(false, false); - } + if (mTimeIdle < 0) + MWBase::Environment::get().getWorld()->toggleVanityMode(false); mTimeIdle = 0.f; } void InputManager::updateIdleTime(float dt) { - if (mTimeIdle >= 0.f) { + if (mTimeIdle >= 0.f) mTimeIdle += dt; - } if (mTimeIdle > 30.f) { - MWBase::Environment::get().getWorld()->toggleVanityMode(true, false); + MWBase::Environment::get().getWorld()->toggleVanityMode(true); mTimeIdle = -1.f; } } diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/camera.cpp similarity index 54% rename from apps/openmw/mwrender/player.cpp rename to apps/openmw/mwrender/camera.cpp index fb0602bda..b4fd6a543 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -1,7 +1,8 @@ -#include "player.hpp" +#include "camera.hpp" #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -14,10 +15,9 @@ namespace MWRender { - Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node) + Camera::Camera (Ogre::Camera *camera) : mCamera(camera), - mPlayerNode(node), - mCameraNode(mPlayerNode->createChildSceneNode()), + mCameraNode(NULL), mFirstPersonView(true), mPreviewMode(false), mFreeLook(true), @@ -28,51 +28,16 @@ namespace MWRender { mVanity.enabled = false; mVanity.allowed = true; - mVanity.forced = false; - - mCameraNode->attachObject(mCamera); - mCameraNode->setPosition(0.f, 0.f, mHeight); mPreviewCam.yaw = 0.f; mPreviewCam.offset = 400.f; } - Player::~Player() - { - delete mAnimation; - } - - bool Player::rotate(const Ogre::Vector3 &rot, bool adjust) + Camera::~Camera() { - 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; - - mVanity.enabled = false; - rotateCamera(rot, adjust); - mVanity.enabled = true; - - compensateYaw(diff); - } - trueRot.z = 0.f; - } - - if (mFreeLook || mVanity.enabled || mPreviewMode) { - rotateCamera(trueRot, adjust); - } - - /// \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) + void Camera::rotateCamera(const Ogre::Vector3 &rot, bool adjust) { if (adjust) { setYaw(getYaw() + rot.z); @@ -81,33 +46,37 @@ namespace MWRender 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 - ); + + Ogre::Quaternion xr(Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_X); if (!mVanity.enabled && !mPreviewMode) { - mPlayerNode->setOrientation(zr); mCameraNode->setOrientation(xr); } else { + Ogre::Quaternion zr(Ogre::Radian(getYaw()), Ogre::Vector3::NEGATIVE_UNIT_Z); mCameraNode->setOrientation(zr * xr); } } - std::string Player::getHandle() const + const std::string &Camera::getHandle() const { - return mPlayerNode->getName(); + return mTrackingPtr.getRefData().getHandle(); } - void Player::attachTo(const MWWorld::Ptr &ptr) + void Camera::attachTo(const MWWorld::Ptr &ptr) { - ptr.getRefData().setBaseNode(mPlayerNode); + mTrackingPtr = ptr; + Ogre::SceneNode *node = mTrackingPtr.getRefData().getBaseNode()->createChildSceneNode(Ogre::Vector3(0.0f, 0.0f, mHeight)); + if(mCameraNode) + { + node->setOrientation(mCameraNode->getOrientation()); + node->setPosition(mCameraNode->getPosition()); + node->setScale(mCameraNode->getScale()); + mCameraNode->getCreator()->destroySceneNode(mCameraNode); + } + mCameraNode = node; + mCameraNode->attachObject(mCamera); } - void Player::updateListener() + void Camera::updateListener() { Ogre::Vector3 pos = mCamera->getRealPosition(); Ogre::Vector3 dir = mCamera->getRealDirection(); @@ -116,29 +85,27 @@ namespace MWRender MWBase::Environment::get().getSoundManager()->setListenerPosDir(pos, dir, up); } - void Player::update(float duration) + void Camera::update(float duration) { updateListener(); // only show the crosshair in game mode and in first person mode. - MWBase::Environment::get().getWindowManager ()->showCrosshair - (!MWBase::Environment::get().getWindowManager ()->isGuiMode () && (mFirstPersonView && !mVanity.enabled && !mPreviewMode)); + MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager(); + wm->showCrosshair(!wm->isGuiMode() && (mFirstPersonView && !mVanity.enabled && !mPreviewMode)); - if (mFirstPersonView && !mVanity.enabled) { - return; - } - if (mVanity.enabled) { + if(mVanity.enabled) + { Ogre::Vector3 rot(0.f, 0.f, 0.f); rot.z = Ogre::Degree(3.f * duration).valueRadians(); rotateCamera(rot, true); } } - void Player::toggleViewMode() + void Camera::toggleViewMode() { mFirstPersonView = !mFirstPersonView; - mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? - NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); + mAnimation->setViewMode(isFirstPerson() ? NpcAnimation::VM_FirstPerson : + NpcAnimation::VM_Normal); if (mFirstPersonView) { mCamera->setPosition(0.f, 0.f, 0.f); setLowHeight(false); @@ -148,28 +115,24 @@ namespace MWRender } } - void Player::allowVanityMode(bool allow) + void Camera::allowVanityMode(bool allow) { - if (!allow && mVanity.enabled && !mVanity.forced) { + if (!allow && mVanity.enabled) toggleVanityMode(false); - } mVanity.allowed = allow; } - bool Player::toggleVanityMode(bool enable, bool force) + bool Camera::toggleVanityMode(bool enable) { - if ((mVanity.forced && !force) || - (!mVanity.allowed && (force || enable))) - { + if(!mVanity.allowed && enable) return false; - } else if (mVanity.enabled == enable) { + + if(mVanity.enabled == enable) return true; - } mVanity.enabled = enable; - mVanity.forced = force && enable; - mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? - NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); + mAnimation->setViewMode(isFirstPerson() ? NpcAnimation::VM_FirstPerson : + NpcAnimation::VM_Normal); float offset = mPreviewCam.offset; Ogre::Vector3 rot(0.f, 0.f, 0.f); @@ -185,20 +148,22 @@ namespace MWRender setLowHeight(!mFirstPersonView); } rot.z = getYaw(); + mCamera->setPosition(0.f, 0.f, offset); rotateCamera(rot, false); return true; } - void Player::togglePreviewMode(bool enable) + void Camera::togglePreviewMode(bool enable) { - if (mPreviewMode == enable) { + if(mPreviewMode == enable) return; - } + mPreviewMode = enable; - mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? - NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); + mAnimation->setViewMode(isFirstPerson() ? NpcAnimation::VM_FirstPerson : + NpcAnimation::VM_Normal); + float offset = mCamera->getPosition().z; if (mPreviewMode) { mMainCam.offset = offset; @@ -211,19 +176,19 @@ namespace MWRender setLowHeight(!mFirstPersonView); } + mCamera->setPosition(0.f, 0.f, offset); rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); } - float Player::getYaw() + float Camera::getYaw() { - if (mVanity.enabled || mPreviewMode) { + if(mVanity.enabled || mPreviewMode) return mPreviewCam.yaw; - } return mMainCam.yaw; } - void Player::setYaw(float angle) + void Camera::setYaw(float angle) { if (angle > Ogre::Math::PI) { angle -= Ogre::Math::TWO_PI; @@ -237,7 +202,7 @@ namespace MWRender } } - float Player::getPitch() + float Camera::getPitch() { if (mVanity.enabled || mPreviewMode) { return mPreviewCam.pitch; @@ -245,18 +210,18 @@ namespace MWRender return mMainCam.pitch; } - void Player::setPitch(float angle) + void Camera::setPitch(float angle) { - const float epsilon = 0.000001; + const float epsilon = 0.000001f; float limit = Ogre::Math::HALF_PI - epsilon; - if (mVanity.forced || mPreviewMode) { - limit /= 2; - } - if (angle > limit) { + if(mPreviewMode) + limit /= 2; + + if(angle > limit) angle = limit; - } else if (angle < -limit) { + else if(angle < -limit) angle = -limit; - } + if (mVanity.enabled || mPreviewMode) { mPreviewCam.pitch = angle; } else { @@ -264,11 +229,11 @@ namespace MWRender } } - void Player::setCameraDistance(float dist, bool adjust, bool override) + void Camera::setCameraDistance(float dist, bool adjust, bool override) { - if (mFirstPersonView && !mPreviewMode && !mVanity.enabled) { + if(mFirstPersonView && !mPreviewMode && !mVanity.enabled) return; - } + Ogre::Vector3 v(0.f, 0.f, dist); if (adjust) { v += mCamera->getPosition(); @@ -293,7 +258,7 @@ namespace MWRender } } - void Player::setCameraDistance() + void Camera::setCameraDistance() { if (mDistanceAdjusted) { if (mVanity.enabled || mPreviewMode) { @@ -305,65 +270,54 @@ namespace MWRender mDistanceAdjusted = false; } - void Player::setAnimation(NpcAnimation *anim) + void Camera::setAnimation(NpcAnimation *anim) { - anim->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? - NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); - - delete mAnimation; + // If we're switching to a new NpcAnimation, ensure the old one is + // using a normal view mode + if(mAnimation && mAnimation != anim) + mAnimation->setViewMode(NpcAnimation::VM_Normal); mAnimation = anim; + mAnimation->setViewMode(isFirstPerson() ? NpcAnimation::VM_FirstPerson : + NpcAnimation::VM_Normal); } - void Player::setHeight(float height) + void Camera::setHeight(float height) { mHeight = height; mCameraNode->setPosition(0.f, 0.f, mHeight); } - float Player::getHeight() + float Camera::getHeight() { - return mHeight * mPlayerNode->getScale().z; + return mHeight * mTrackingPtr.getRefData().getBaseNode()->getScale().z; } - bool Player::getPosition(Ogre::Vector3 &player, Ogre::Vector3 &camera) + bool Camera::getPosition(Ogre::Vector3 &player, Ogre::Vector3 &camera) { mCamera->getParentSceneNode ()->needUpdate(true); camera = mCamera->getRealPosition(); - player = mPlayerNode->getPosition(); + player = mTrackingPtr.getRefData().getBaseNode()->getPosition(); return mFirstPersonView && !mVanity.enabled && !mPreviewMode; } - Ogre::Vector3 Player::getPosition() + Ogre::Vector3 Camera::getPosition() { - return mPlayerNode->getPosition(); + return mTrackingPtr.getRefData().getBaseNode()->getPosition(); } - void Player::getSightAngles(float &pitch, float &yaw) + void Camera::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) + void Camera::togglePlayerLooking(bool enable) { mFreeLook = enable; } - void Player::setLowHeight(bool low) + void Camera::setLowHeight(bool low) { if (low) { mCameraNode->setPosition(0.f, 0.f, mHeight * 0.85); @@ -372,7 +326,7 @@ namespace MWRender } } - bool Player::isVanityOrPreviewModeEnabled() + bool Camera::isVanityOrPreviewModeEnabled() { return mPreviewMode || mVanity.enabled; } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/camera.hpp similarity index 71% rename from apps/openmw/mwrender/player.hpp rename to apps/openmw/mwrender/camera.hpp index 9de41823d..7bbdd303d 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -1,8 +1,10 @@ -#ifndef GAME_MWRENDER_PLAYER_H -#define GAME_MWRENDER_PLAYER_H +#ifndef GAME_MWRENDER_CAMERA_H +#define GAME_MWRENDER_CAMERA_H #include +#include "../mwworld/ptr.hpp" + namespace Ogre { class Vector3; @@ -10,24 +12,20 @@ namespace Ogre class SceneNode; } -namespace MWWorld -{ - class Ptr; -} - namespace MWRender { class NpcAnimation; - /// \brief Player character rendering and camera control - class Player + + /// \brief Camera control + class Camera { struct CamData { float pitch, yaw, offset; }; - Ogre::Camera *mCamera; + MWWorld::Ptr mTrackingPtr; - Ogre::SceneNode *mPlayerNode; + Ogre::Camera *mCamera; Ogre::SceneNode *mCameraNode; NpcAnimation *mAnimation; @@ -37,7 +35,7 @@ namespace MWRender bool mFreeLook; struct { - bool enabled, allowed, forced; + bool enabled, allowed; } mVanity; float mHeight, mCameraDistance; @@ -51,15 +49,11 @@ namespace MWRender void setLowHeight(bool low = true); public: + Camera(Ogre::Camera *camera); + ~Camera(); - Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); - ~Player(); - - /// Set where the player is looking at. Uses Morrowind (euler) angles + /// Set where the camera is looking at. Uses Morrowind (euler) angles /// \param rot Rotation angles in radians - /// \return true if player object needs to bo rotated physically - bool rotate(const Ogre::Vector3 &rot, bool adjust); - void rotateCamera(const Ogre::Vector3 &rot, bool adjust); float getYaw(); @@ -68,22 +62,21 @@ namespace MWRender float getPitch(); void setPitch(float angle); - void compensateYaw(float diff); - - std::string getHandle() const; + const std::string &getHandle() const; /// Attach camera to object - /// \note there is no protection from attaching the same camera to - /// several different objects void attachTo(const MWWorld::Ptr &); void toggleViewMode(); - bool toggleVanityMode(bool enable, bool force = false); + bool toggleVanityMode(bool enable); void allowVanityMode(bool allow); void togglePreviewMode(bool enable); + bool isFirstPerson() const + { return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); } + void update(float duration); /// Set camera distance for current mode. Don't work on 1st person view. @@ -96,8 +89,6 @@ namespace MWRender void setCameraDistance(); void setAnimation(NpcAnimation *anim); - NpcAnimation *getAnimation() const - { return mAnimation; } void setHeight(float height); float getHeight(); diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 24b089db3..4d9680b2c 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -12,6 +12,7 @@ #include "../mwbase/world.hpp" #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/inventorystore.hpp" #include "renderconst.hpp" #include "npcanimation.hpp" @@ -134,6 +135,46 @@ namespace MWRender void InventoryPreview::update(int sizeX, int sizeY) { + MWWorld::InventoryStore &inv = MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter); + MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + std::string groupname; + if(iter == inv.end()) + groupname = "inventoryhandtohand"; + else + { + const std::string &type = iter->getTypeName(); + if(type == typeid(ESM::Lockpick).name() || type == typeid(ESM::Probe).name()) + groupname = "inventoryweapononehand"; + else if(type == typeid(ESM::Weapon).name()) + { + MWWorld::LiveCellRef *ref = iter->get(); + + int type = ref->mBase->mData.mType; + if(type == ESM::Weapon::ShortBladeOneHand || + type == ESM::Weapon::LongBladeOneHand || + type == ESM::Weapon::BluntOneHand || + type == ESM::Weapon::AxeOneHand) + groupname = "inventoryweapononehand"; + else if(type == ESM::Weapon::LongBladeTwoHand || + type == ESM::Weapon::BluntTwoClose || + type == ESM::Weapon::AxeTwoHand) + groupname = "inventoryweapontwohand"; + else if(type == ESM::Weapon::BluntTwoWide || + type == ESM::Weapon::SpearTwoWide) + groupname = "inventoryweapontwowide"; + else + groupname = "inventoryhandtohand"; + } + else + groupname = "inventoryhandtohand"; + } + + if(groupname != mCurrentAnimGroup) + { + mCurrentAnimGroup = groupname; + mAnimation->play(mCurrentAnimGroup, "start", "stop", 0.0f, 0); + } + mAnimation->forceUpdate(); mAnimation->runAnimation(0.0f); @@ -155,7 +196,10 @@ namespace MWRender if (!mSelectionBuffer) mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0); - mAnimation->play("inventoryhandtohand", "start", "stop", 0.0f, 0); + mAnimation->showWeapons(true); + + mCurrentAnimGroup = "inventoryhandtohand"; + mAnimation->play(mCurrentAnimGroup, "start", "stop", 0.0f, 0); } // -------------------------------------------------------------------------------------------------- diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index 08cbd5108..d8f43f71b 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -53,6 +53,7 @@ namespace MWRender MWWorld::Ptr mCharacter; MWRender::NpcAnimation* mAnimation; + std::string mCurrentAnimGroup; std::string mName; diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index 54f288bff..b318c2d56 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -20,7 +20,6 @@ #include "../mwworld/ptr.hpp" -#include "player.hpp" #include "renderconst.hpp" using namespace Ogre; diff --git a/apps/openmw/mwrender/debugging.hpp b/apps/openmw/mwrender/debugging.hpp index 6a4eef58f..4a574017c 100644 --- a/apps/openmw/mwrender/debugging.hpp +++ b/apps/openmw/mwrender/debugging.hpp @@ -39,8 +39,6 @@ namespace MWWorld namespace MWRender { - class Player; - class Debugging { OEngine::Physic::PhysicEngine* mEngine; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 1d1ebf6b6..a92092020 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -178,7 +178,8 @@ void NpcAnimation::updateParts(bool forceupdate) { &NpcAnimation::mGloveR, MWWorld::InventoryStore::Slot_RightGauntlet, 0 }, { &NpcAnimation::mShirt, MWWorld::InventoryStore::Slot_Shirt, 0 }, { &NpcAnimation::mPants, MWWorld::InventoryStore::Slot_Pants, 0 }, - { &NpcAnimation::mShield, MWWorld::InventoryStore::Slot_CarriedLeft, 0 } + { &NpcAnimation::mShield, MWWorld::InventoryStore::Slot_CarriedLeft, 0 }, + { &NpcAnimation::mWeapon, MWWorld::InventoryStore::Slot_CarriedRight, 0 } }; static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]); @@ -239,7 +240,7 @@ void NpcAnimation::updateParts(bool forceupdate) ESM::PRT_RForearm, ESM::PRT_LForearm, ESM::PRT_RPauldron, ESM::PRT_LPauldron }; size_t parts_size = sizeof(parts)/sizeof(parts[0]); - for(int p = 0;p < static_cast (parts_size);++p) + for(size_t p = 0;p < parts_size;++p) reserveIndividualPart(parts[p], slotlist[i].mSlot, prio); } else if(slotlist[i].mSlot == MWWorld::InventoryStore::Slot_Skirt) @@ -260,29 +261,7 @@ void NpcAnimation::updateParts(bool forceupdate) if(mViewMode == VM_HeadOnly) return; - std::map bodypartMap; - bodypartMap[ESM::PRT_Neck] = ESM::BodyPart::MP_Neck; - bodypartMap[ESM::PRT_Cuirass] = ESM::BodyPart::MP_Chest; - bodypartMap[ESM::PRT_Groin] = ESM::BodyPart::MP_Groin; - bodypartMap[ESM::PRT_RHand] = ESM::BodyPart::MP_Hand; - bodypartMap[ESM::PRT_LHand] = ESM::BodyPart::MP_Hand; - bodypartMap[ESM::PRT_RWrist] = ESM::BodyPart::MP_Wrist; - bodypartMap[ESM::PRT_LWrist] = ESM::BodyPart::MP_Wrist; - bodypartMap[ESM::PRT_RForearm] = ESM::BodyPart::MP_Forearm; - bodypartMap[ESM::PRT_LForearm] = ESM::BodyPart::MP_Forearm; - bodypartMap[ESM::PRT_RUpperarm] = ESM::BodyPart::MP_Upperarm; - bodypartMap[ESM::PRT_LUpperarm] = ESM::BodyPart::MP_Upperarm; - bodypartMap[ESM::PRT_RFoot] = ESM::BodyPart::MP_Foot; - bodypartMap[ESM::PRT_LFoot] = ESM::BodyPart::MP_Foot; - bodypartMap[ESM::PRT_RAnkle] = ESM::BodyPart::MP_Ankle; - bodypartMap[ESM::PRT_LAnkle] = ESM::BodyPart::MP_Ankle; - bodypartMap[ESM::PRT_RKnee] = ESM::BodyPart::MP_Knee; - bodypartMap[ESM::PRT_LKnee] = ESM::BodyPart::MP_Knee; - bodypartMap[ESM::PRT_RLeg] = ESM::BodyPart::MP_Upperleg; - bodypartMap[ESM::PRT_LLeg] = ESM::BodyPart::MP_Upperleg; - bodypartMap[ESM::PRT_Tail] = ESM::BodyPart::MP_Tail; - - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + showWeapons(mShowWeapons); const int Flag_Female = 0x01; const int Flag_FirstPerson = 0x02; @@ -299,21 +278,43 @@ void NpcAnimation::updateParts(bool forceupdate) std::pair thisCombination = std::make_pair(race, flags); if (sRaceMapping.find(thisCombination) == sRaceMapping.end()) { - sRaceMapping[thisCombination].resize(ESM::PRT_Count); - for (int i=0; i bodypartMap; + if(bodypartMap.size() == 0) + { + bodypartMap[ESM::PRT_Neck] = ESM::BodyPart::MP_Neck; + bodypartMap[ESM::PRT_Cuirass] = ESM::BodyPart::MP_Chest; + bodypartMap[ESM::PRT_Groin] = ESM::BodyPart::MP_Groin; + bodypartMap[ESM::PRT_RHand] = ESM::BodyPart::MP_Hand; + bodypartMap[ESM::PRT_LHand] = ESM::BodyPart::MP_Hand; + bodypartMap[ESM::PRT_RWrist] = ESM::BodyPart::MP_Wrist; + bodypartMap[ESM::PRT_LWrist] = ESM::BodyPart::MP_Wrist; + bodypartMap[ESM::PRT_RForearm] = ESM::BodyPart::MP_Forearm; + bodypartMap[ESM::PRT_LForearm] = ESM::BodyPart::MP_Forearm; + bodypartMap[ESM::PRT_RUpperarm] = ESM::BodyPart::MP_Upperarm; + bodypartMap[ESM::PRT_LUpperarm] = ESM::BodyPart::MP_Upperarm; + bodypartMap[ESM::PRT_RFoot] = ESM::BodyPart::MP_Foot; + bodypartMap[ESM::PRT_LFoot] = ESM::BodyPart::MP_Foot; + bodypartMap[ESM::PRT_RAnkle] = ESM::BodyPart::MP_Ankle; + bodypartMap[ESM::PRT_LAnkle] = ESM::BodyPart::MP_Ankle; + bodypartMap[ESM::PRT_RKnee] = ESM::BodyPart::MP_Knee; + bodypartMap[ESM::PRT_LKnee] = ESM::BodyPart::MP_Knee; + bodypartMap[ESM::PRT_RLeg] = ESM::BodyPart::MP_Upperleg; + bodypartMap[ESM::PRT_LLeg] = ESM::BodyPart::MP_Upperleg; + bodypartMap[ESM::PRT_Tail] = ESM::BodyPart::MP_Tail; + } - const MWWorld::Store &partStore = store.get(); + sRaceMapping[thisCombination].resize(ESM::PRT_Count, NULL); - for (MWWorld::Store::iterator it = partStore.begin(); it != partStore.end(); ++it) + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::Store &partStore = store.get(); + for(MWWorld::Store::iterator it = partStore.begin(); it != partStore.end(); ++it) { const ESM::BodyPart& bodypart = *it; if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable) continue; if (bodypart.mData.mType != ESM::BodyPart::MT_Skin) - { continue; - } + if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female)) continue; if (!Misc::StringUtils::ciEqual(bodypart.mRace, mNpc->mRace)) @@ -480,7 +481,7 @@ void NpcAnimation::showWeapons(bool showWeapon) if(mWeapon != inv.end()) // special case for weapons { std::string mesh = MWWorld::Class::get(*mWeapon).getModel(*mWeapon); - addOrReplaceIndividualPart(ESM::PRT_Weapon,-1,1,mesh); + addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1, mesh); } } else diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index da51f10c1..60a9b22a3 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -49,12 +49,14 @@ using namespace Ogre; namespace MWRender { -RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, - const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine,MWWorld::Fallback* fallback) +RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, + const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine, + MWWorld::Fallback* fallback) : mRendering(_rend) , mFallback(fallback) - , mObjects(mRendering,mFallback) + , mObjects(mRendering, mFallback) , mActors(mRendering, this) + , mPlayerAnimation(NULL) , mAmbientMode(0) , mSunEnabled(0) , mPhysicsEngine(engine) @@ -148,14 +150,13 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const applyCompositors(); - SceneNode *rt = mRendering.getScene()->getRootSceneNode(); - mRootNode = rt; + mRootNode = mRendering.getScene()->getRootSceneNode(); + mRootNode->createChildSceneNode("player"); mObjects.setRootNode(mRootNode); mActors.setRootNode(mRootNode); - Ogre::SceneNode *playerNode = mRootNode->createChildSceneNode ("player"); - mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); + mCamera = new MWRender::Camera(mRendering.getCamera()); mShadows = new Shadows(&mRendering); @@ -183,7 +184,8 @@ RenderingManager::~RenderingManager () mRendering.getWindow()->removeListener(this); mRendering.removeWindowEventListener(this); - delete mPlayer; + delete mPlayerAnimation; + delete mCamera; delete mSkyManager; delete mDebugging; delete mShadows; @@ -264,37 +266,20 @@ void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3 ptr.getRefData().getBaseNode()->setScale(scale); } -bool RenderingManager::rotateObject(const MWWorld::Ptr &ptr, Ogre::Vector3 &rot, bool adjust) +void RenderingManager::rotateObject(const MWWorld::Ptr &ptr) { - bool isActive = ptr.getRefData().getBaseNode() != 0; - bool isPlayer = isActive && ptr.getRefData().getHandle() == "player"; - bool force = true; + Ogre::Vector3 rot(ptr.getRefData().getPosition().rot); - if (isPlayer) - force = mPlayer->rotate(rot, adjust); + if(ptr.getRefData().getHandle() == mCamera->getHandle() && + !mCamera->isVanityOrPreviewModeEnabled()) + mCamera->rotateCamera(rot, false); - MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z); - if (!isPlayer && isActive) - { - if(adjust) - { - const float *objRot = ptr.getRefData().getPosition().rot; - rot.x += objRot[0]; - rot.y += objRot[1]; - rot.z += objRot[2]; - } + Ogre::Quaternion newo = Ogre::Quaternion(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z); + if(!MWWorld::Class::get(ptr).isActor()) + newo = Ogre::Quaternion(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X) * + Ogre::Quaternion(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y) * newo; - Ogre::Quaternion newo = Ogre::Quaternion(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X) * - Ogre::Quaternion(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y) * - Ogre::Quaternion(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z); - ptr.getRefData().getBaseNode()->setOrientation(newo); - } - else if(isPlayer) - { - rot.x = -mPlayer->getPitch(); - rot.z = mPlayer->getYaw(); - } - return force; + ptr.getRefData().getBaseNode()->setOrientation(newo); } void @@ -317,7 +302,7 @@ void RenderingManager::update (float duration, bool paused) { MWBase::World *world = MWBase::Environment::get().getWorld(); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude; mRendering.getFader()->setFactor(1.f-(blind / 100.f)); @@ -330,16 +315,16 @@ void RenderingManager::update (float duration, bool paused) Ogre::Vector3 playerPos(_playerPos[0], _playerPos[1], _playerPos[2]); Ogre::Vector3 orig, dest; - mPlayer->setCameraDistance(); - if (!mPlayer->getPosition(orig, dest)) { - orig.z += mPlayer->getHeight() * mRootNode->getScale().z; + mCamera->setCameraDistance(); + if(!mCamera->getPosition(orig, dest)) + { + orig.z += mCamera->getHeight() * mRootNode->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); + std::pair test = mPhysicsEngine->rayTest(btOrig, btDest); if (!test.first.empty()) { - mPlayer->setCameraDistance(test.second * orig.distance(dest), false, false); + mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); } } @@ -353,14 +338,12 @@ void RenderingManager::update (float duration, bool paused) Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); - applyFog(world->isUnderwater (world->getPlayer().getPlayer().getCell(), cam)); + applyFog(world->isUnderwater(player.getCell(), cam)); if(paused) - { return; - } - mPlayer->update(duration); + mCamera->update(duration); mActors.update (duration); mObjects.update (duration); @@ -371,18 +354,11 @@ void RenderingManager::update (float duration, bool paused) mSkyManager->setGlare(mOcclusionQuery->getSunVisibility()); Ogre::SceneNode *node = data.getBaseNode(); - //Ogre::Quaternion orient = - //node->convertLocalToWorldOrientation(node->_getDerivedOrientation()); - Ogre::Quaternion orient = -node->_getDerivedOrientation(); + Ogre::Quaternion orient = node->_getDerivedOrientation(); mLocalMap->updatePlayer(playerPos, orient); - mWater->updateUnderwater( - world->isUnderwater( - world->getPlayer().getPlayer().getCell(), - cam) - ); + mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam)); mWater->update(duration, playerPos); } @@ -876,39 +852,49 @@ void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned i } } -void RenderingManager::attachCameraTo(const MWWorld::Ptr &ptr) +void RenderingManager::setupPlayer(const MWWorld::Ptr &ptr) { - mPlayer->attachTo(ptr); + ptr.getRefData().setBaseNode(mRendering.getScene()->getSceneNode("player")); + mCamera->attachTo(ptr); } void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr) { - MWRender::NpcAnimation *anim = - new MWRender::NpcAnimation( - ptr, ptr.getRefData ().getBaseNode (), - MWWorld::Class::get(ptr).getInventoryStore(ptr), RV_Actors - ); - mPlayer->setAnimation(anim); - mWater->removeEmitter (ptr); - mWater->addEmitter (ptr); + if(!mPlayerAnimation) + { + mPlayerAnimation = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(), + MWWorld::Class::get(ptr).getInventoryStore(ptr), + RV_Actors); + } + else + { + // Reconstruct the NpcAnimation in-place + mPlayerAnimation->~NpcAnimation(); + new(mPlayerAnimation) NpcAnimation(ptr, ptr.getRefData().getBaseNode(), + MWWorld::Class::get(ptr).getInventoryStore(ptr), + RV_Actors); + } + mCamera->setAnimation(mPlayerAnimation); + mWater->removeEmitter(ptr); + mWater->addEmitter(ptr); // apply race height MWBase::Environment::get().getWorld()->scaleObject(ptr, 1.f); } -void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw) +void RenderingManager::getCameraData(Ogre::Vector3 &eyepos, float &pitch, float &yaw) { - eyepos = mPlayer->getPosition(); - eyepos.z += mPlayer->getHeight(); - mPlayer->getSightAngles(pitch, yaw); + eyepos = mCamera->getPosition(); + eyepos.z += mCamera->getHeight(); + mCamera->getSightAngles(pitch, yaw); } -bool RenderingManager::vanityRotateCamera(float* rot) +bool RenderingManager::vanityRotateCamera(const float *rot) { - if(!mPlayer->isVanityOrPreviewModeEnabled()) + if(!mCamera->isVanityOrPreviewModeEnabled()) return false; Ogre::Vector3 vRot(rot); - mPlayer->rotateCamera(vRot, true); + mCamera->rotateCamera(vRot, true); return true; } @@ -931,7 +917,7 @@ Animation* RenderingManager::getAnimation(const MWWorld::Ptr &ptr) { Animation *anim = mActors.getAnimation(ptr); if(!anim && ptr.getRefData().getHandle() == "player") - anim = mPlayer->getAnimation(); + anim = mPlayerAnimation; return anim; } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index cece7a95f..6a35bfb6d 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -17,7 +17,7 @@ #include "objects.hpp" #include "actors.hpp" -#include "player.hpp" +#include "camera.hpp" #include "occlusionquery.hpp" namespace Ogre @@ -50,49 +50,44 @@ namespace MWRender class VideoPlayer; class Animation; -class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener, public Ogre::RenderTargetListener { - - private: - - +class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener, public Ogre::RenderTargetListener +{ +private: virtual MWRender::Objects& getObjects(); virtual MWRender::Actors& getActors(); - public: +public: RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, - const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine,MWWorld::Fallback* fallback); + const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine, + MWWorld::Fallback* fallback); virtual ~RenderingManager(); - void togglePOV() { - mPlayer->toggleViewMode(); - } + void togglePOV() + { mCamera->toggleViewMode(); } - void togglePreviewMode(bool enable) { - mPlayer->togglePreviewMode(enable); - } + void togglePreviewMode(bool enable) + { mCamera->togglePreviewMode(enable); } - bool toggleVanityMode(bool enable, bool force) { - return mPlayer->toggleVanityMode(enable, force); - } + bool toggleVanityMode(bool enable) + { return mCamera->toggleVanityMode(enable); } - void allowVanityMode(bool allow) { - mPlayer->allowVanityMode(allow); - } + void allowVanityMode(bool allow) + { mCamera->allowVanityMode(allow); } - void togglePlayerLooking(bool enable) { - mPlayer->togglePlayerLooking(enable); - } + void togglePlayerLooking(bool enable) + { mCamera->togglePlayerLooking(enable); } - void changeVanityModeScale(float factor) { - if (mPlayer->isVanityOrPreviewModeEnabled()) - mPlayer->setCameraDistance(-factor/120.f*10, true, true); + void changeVanityModeScale(float factor) + { + if(mCamera->isVanityOrPreviewModeEnabled()) + mCamera->setCameraDistance(-factor/120.f*10, true, true); } - bool vanityRotateCamera(float* rot); + bool vanityRotateCamera(const float *rot); - void getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw); + void getCameraData(Ogre::Vector3 &eyepos, float &pitch, float &yaw); - void attachCameraTo(const MWWorld::Ptr &ptr); + void setupPlayer(const MWWorld::Ptr &ptr); void renderPlayer(const MWWorld::Ptr &ptr); SkyManager* getSkyManager(); @@ -121,11 +116,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position); void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale); - /// Rotates object accordingly to its type - /// \param rot euler angles in radians - /// \param adjust indicates should rotation be set or adjusted - /// \return true if object needs to be rotated physically - bool rotateObject (const MWWorld::Ptr& ptr, Ogre::Vector3 &rot, bool adjust = false); + /// Updates an object's rotation + void rotateObject (const MWWorld::Ptr& ptr); void setWaterHeight(const float height); void toggleWater(); @@ -207,12 +199,11 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void stopVideo(); void frameStarted(float dt); - protected: - virtual void windowResized(Ogre::RenderWindow* rw); +protected: + virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw); - private: - +private: sh::Factory* mFactory; void setAmbientMode(); @@ -241,6 +232,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList MWRender::Objects mObjects; MWRender::Actors mActors; + MWRender::NpcAnimation *mPlayerAnimation; + // 0 normal, 1 more bright, 2 max int mAmbientMode; @@ -255,7 +248,7 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList OEngine::Physic::PhysicEngine* mPhysicsEngine; - MWRender::Player *mPlayer; + MWRender::Camera *mCamera; MWRender::Debugging *mDebugging; diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 7f3abce70..516b48dde 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -205,7 +205,7 @@ unsigned int Moon::getPhaseInt() const return 0; } -SkyManager::SkyManager (SceneNode* root, Camera* pCamera) +SkyManager::SkyManager(Ogre::SceneNode *root, Ogre::Camera *pCamera) : mHour(0.0f) , mDay(0) , mMonth(0) diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index daf64c0d5..a08563877 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -282,10 +282,8 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); - if (world->toggleVanityMode(sActivate, true)) { - context.report( - (sActivate) ? "Vanity Mode -> On" : "Vanity Mode -> Off" - ); + if (world->toggleVanityMode(sActivate)) { + context.report(sActivate ? "Vanity Mode -> On" : "Vanity Mode -> Off"); sActivate = !sActivate; } else { context.report("Vanity Mode -> No"); diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 34e6036e6..ce32b79e5 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -144,7 +144,7 @@ namespace MWWorld // FIXME: This works, but it's inconcsistent with how the rotations are applied elsewhere. Why? return position + (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)* Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)* - Ogre::Quaternion(Ogre::Radian( -refpos.rot[0]), Ogre::Vector3::UNIT_X)) * + Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * movement; } @@ -160,7 +160,7 @@ namespace MWWorld { velocity = (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)* Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)* - Ogre::Quaternion(Ogre::Radian( -refpos.rot[0]), Ogre::Vector3::UNIT_X)) * + Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * movement / time; } else @@ -260,14 +260,13 @@ namespace MWWorld std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world, float queryDistance) { btVector3 dir(0, 1, 0); - dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); - dir = dir.rotate(btVector3(0, 0, 1), mPlayerData.yaw); + dir = dir.rotate(btVector3(1, 0, 0), mCameraData.pitch); + dir = dir.rotate(btVector3(0, 0, 1), mCameraData.yaw); dir.setX(-dir.x()); - btVector3 origin( - mPlayerData.eyepos.x, - mPlayerData.eyepos.y, - mPlayerData.eyepos.z); + btVector3 origin(mCameraData.eyepos.x, + mCameraData.eyepos.y, + mCameraData.eyepos.z); origin += dir * 5; btVector3 dest = origin + dir * queryDistance; @@ -280,14 +279,13 @@ namespace MWWorld std::vector < std::pair > PhysicsSystem::getFacedHandles (float queryDistance) { btVector3 dir(0, 1, 0); - dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); - dir = dir.rotate(btVector3(0, 0, 1), mPlayerData.yaw); + dir = dir.rotate(btVector3(1, 0, 0), mCameraData.pitch); + dir = dir.rotate(btVector3(0, 0, 1), mCameraData.yaw); dir.setX(-dir.x()); - btVector3 origin( - mPlayerData.eyepos.x, - mPlayerData.eyepos.y, - mPlayerData.eyepos.z); + btVector3 origin(mCameraData.eyepos.x, + mCameraData.eyepos.y, + mCameraData.eyepos.z); origin += dir * 5; btVector3 dest = origin + dir * queryDistance; @@ -552,10 +550,10 @@ namespace MWWorld return true; } - void PhysicsSystem::updatePlayerData(Ogre::Vector3 &eyepos, float pitch, float yaw) + void PhysicsSystem::updateCameraData(const Ogre::Vector3 &eyepos, float pitch, float yaw) { - mPlayerData.eyepos = eyepos; - mPlayerData.pitch = pitch; - mPlayerData.yaw = yaw; + mCameraData.eyepos = eyepos; + mCameraData.pitch = pitch; + mCameraData.yaw = yaw; } } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 48214029e..3322c38a6 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -77,13 +77,13 @@ namespace MWWorld bool getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max); - void updatePlayerData(Ogre::Vector3 &eyepos, float pitch, float yaw); + void updateCameraData(const Ogre::Vector3 &eyepos, float pitch, float yaw); private: struct { Ogre::Vector3 eyepos; float pitch, yaw; - } mPlayerData; + } mCameraData; OEngine::Render::OgreRenderer &mRender; OEngine::Physic::PhysicEngine* mEngine; diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index db565c451..c1a3ae785 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -81,10 +81,13 @@ namespace MWWorld {} } - std::string RefData::getHandle() + const std::string &RefData::getHandle() { - if (!mBaseNode) - return ""; + if(!mBaseNode) + { + static const std::string empty; + return empty; + } return mBaseNode->getName(); } diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 77ceb3721..642f5412c 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -60,7 +60,7 @@ namespace MWWorld RefData& operator= (const RefData& refData); /// Return OGRE handle (may be empty). - std::string getHandle(); + const std::string &getHandle(); /// Return OGRE base node (can be a null pointer). Ogre::SceneNode* getBaseNode(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c5970a32c..a903369ee 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -18,7 +18,6 @@ #include "../mwmechanics/movement.hpp" #include "../mwrender/sky.hpp" -#include "../mwrender/player.hpp" #include "../mwclass/door.hpp" @@ -813,33 +812,50 @@ namespace MWWorld void World::rotateObjectImp (const Ptr& ptr, Ogre::Vector3 rot, bool adjust) { - if (mRendering->rotateObject(ptr, rot, adjust)) + const float two_pi = Ogre::Math::TWO_PI; + const float pi = Ogre::Math::PI; + + float *objRot = ptr.getRefData().getPosition().rot; + if(adjust) + { + objRot[0] += rot.x; + objRot[1] += rot.y; + objRot[2] += rot.z; + } + else { - // rotate physically iff renderer confirm so - float *objRot = ptr.getRefData().getPosition().rot; objRot[0] = rot.x; objRot[1] = rot.y; objRot[2] = rot.z; + } - float fullRotateRad=Ogre::Degree(360).valueRadians(); + if(Class::get(ptr).isActor()) + { + /* HACK? Actors shouldn't really be rotating around X (or Y), but + * currently it's done so for rotating the camera, which needs + * clamping. + */ + const float half_pi = Ogre::Math::HALF_PI; + + if(objRot[0] < -half_pi) objRot[0] = -half_pi; + else if(objRot[0] > half_pi) objRot[0] = half_pi; + } + else + { + while(objRot[0] < -pi) objRot[0] += two_pi; + while(objRot[0] > pi) objRot[0] -= two_pi; + } - while(objRot[0]>=fullRotateRad) - objRot[0] -= fullRotateRad; - while(objRot[1]>=fullRotateRad) - objRot[1] -= fullRotateRad; - while(objRot[2]>=fullRotateRad) - objRot[2] -= fullRotateRad; - - while(objRot[0]<=-fullRotateRad) - objRot[0] += fullRotateRad; - while(objRot[1]<=-fullRotateRad) - objRot[1] += fullRotateRad; - while(objRot[2]<=-fullRotateRad) - objRot[2] += fullRotateRad; - - if (ptr.getRefData().getBaseNode() != 0) { - mPhysics->rotateObject(ptr); - } + while(objRot[1] < -pi) objRot[1] += two_pi; + while(objRot[1] > pi) objRot[1] -= two_pi; + + while(objRot[2] < -pi) objRot[2] += two_pi; + while(objRot[2] > pi) objRot[2] -= two_pi; + + if(ptr.getRefData().getBaseNode() != 0) + { + mRendering->rotateObject(ptr); + mPhysics->rotateObject(ptr); } } @@ -1136,8 +1152,8 @@ namespace MWWorld float pitch, yaw; Ogre::Vector3 eyepos; - mRendering->getPlayerData(eyepos, pitch, yaw); - mPhysics->updatePlayerData(eyepos, pitch, yaw); + mRendering->getCameraData(eyepos, pitch, yaw); + mPhysics->updateCameraData(eyepos, pitch, yaw); performUpdateSceneQueries (); @@ -1483,13 +1499,15 @@ namespace MWWorld void World::setupPlayer() { - const ESM::NPC* player = mStore.get().find ("player"); - mPlayer = new MWWorld::Player (player, *this); - mRendering->attachCameraTo(mPlayer->getPlayer()); + const ESM::NPC *player = mStore.get().find("player"); + mPlayer = new MWWorld::Player(player, *this); + + Ptr ptr = mPlayer->getPlayer(); + mRendering->setupPlayer(ptr); if (mNewGame) { - MWWorld::Class::get(mPlayer->getPlayer()).getContainerStore(mPlayer->getPlayer()).fill(player->mInventory, "", mStore); - MWWorld::Class::get(mPlayer->getPlayer()).getInventoryStore(mPlayer->getPlayer()).autoEquip (mPlayer->getPlayer()); + MWWorld::Class::get(ptr).getContainerStore(ptr).fill(player->mInventory, "", mStore); + MWWorld::Class::get(ptr).getInventoryStore(ptr).autoEquip(ptr); } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 339779534..f61f67062 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -355,8 +355,8 @@ namespace MWWorld mRendering->togglePreviewMode(enable); } - virtual bool toggleVanityMode(bool enable, bool force) { - return mRendering->toggleVanityMode(enable, force); + virtual bool toggleVanityMode(bool enable) { + return mRendering->toggleVanityMode(enable); } virtual void allowVanityMode(bool allow) { diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index a66bd99db..cb7c2feb0 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -207,7 +207,7 @@ struct RecordFactoryEntry { static const RecordFactoryEntry recordFactories [] = { { "NiNode", &construct , RC_NiNode }, - { "AvoidNode", &construct , RC_NiNode }, + { "AvoidNode", &construct , RC_AvoidNode }, { "NiBSParticleNode", &construct , RC_NiBSParticleNode }, { "NiBSAnimationNode", &construct , RC_NiBSAnimationNode }, { "NiBillboardNode", &construct , RC_NiNode }, diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 3f852ed83..87e342dca 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -36,6 +36,7 @@ enum RecordType { RC_MISSING = 0, RC_NiNode, + RC_AvoidNode, RC_NiTriShape, RC_NiRotatingParticles, RC_NiAutoNormalParticles, diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index a3eff95c3..a1e2cd8d1 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -185,6 +185,10 @@ void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node * else isCollisionNode = isCollisionNode && (node->recType != Nif::RC_RootCollisionNode); + // Don't collide with AvoidNode shapes + if(node->recType == Nif::RC_AvoidNode) + flags |= 0x800; + // Marker objects /// \todo don't do this in the editor std::string nodename = node->name;