diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index e29e3c268..2f70d14fa 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -214,8 +214,8 @@ private: void toggleMainMenu() { - if (windows.isGuiMode () && windows.getMode () == MWGui::GM_MainMenu) - windows.removeGuiMode (MWGui::GM_MainMenu); + if (windows.isGuiMode () && (windows.getMode () == MWGui::GM_MainMenu || windows.getMode () == MWGui::GM_Settings)) + windows.popGuiMode(); else windows.pushGuiMode (MWGui::GM_MainMenu); } diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index f05ea80ce..94a3f71c8 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -27,7 +27,13 @@ namespace MWRender // we are only interested in X and Y rotation // Rotate around X axis - Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); + 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); + } + Ogre::Quaternion xr(radx, Ogre::Vector3::UNIT_X); // Rotate around Y axis Ogre::Quaternion yr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Y); @@ -35,7 +41,6 @@ namespace MWRender pitchNode->setOrientation(xr); yawNode->setOrientation(yr); - controlFlip(); updateListener(); return !mVanityModeEnabled; @@ -56,35 +61,36 @@ namespace MWRender Ogre::SceneNode *pitchNode = mCamera->getParentSceneNode(); Ogre::SceneNode *yawNode = pitchNode->getParentSceneNode(); - pitchNode->pitch(Ogre::Radian(rot.x)); + float f = controlFlip(Ogre::Radian(rot.x).valueDegrees()); + if (f != 0.0) { + pitchNode->pitch(Ogre::Degree(f)); + } yawNode->yaw(Ogre::Radian(-rot.z)); - controlFlip(); updateListener(); return !mVanityModeEnabled; } - void Player::controlFlip() + float Player::controlFlip(float shift) { Ogre::SceneNode *pitchNode = mCamera->getParentSceneNode(); Ogre::Quaternion orient = pitchNode->getOrientation(); float pitchAngle = - (2 * Ogre::Degree(Ogre::Math::ACos(orient.w)).valueDegrees()); + (2 * Ogre::Degree(Ogre::Math::ASin(orient.x)).valueDegrees()); - // Limit the pitch between -90 degress and +90 degrees, Quake3-style. - if (pitchAngle > 90.0f) - { - Ogre::Real sqrt = Ogre::Math::Sqrt(0.5f); - if (orient.x > 0) { - // Set orientation to 90 degrees on X-axis. - pitchNode->setOrientation(Ogre::Quaternion(sqrt, sqrt, 0, 0)); - } else if (orient.x < 0) { - // Sets orientation to -90 degrees on X-axis. - pitchNode->setOrientation(Ogre::Quaternion(sqrt, -sqrt, 0, 0)); - } + if (pitchAngle + shift < 89.5f && pitchAngle + shift > -89.5f) { + return shift; } + 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; + } + return 0.f; } void Player::updateListener() diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index a19e72ab0..981ecfe0b 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -27,7 +27,7 @@ namespace MWRender bool mFirstPersonView; bool mVanityModeEnabled; - void controlFlip(); + float controlFlip(float shift = 0.f); /// Updates sound manager listener data void updateListener(); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7180fea66..521521875 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -254,7 +254,8 @@ RenderingManager::rotateObject( Ogre::Vector3 &rot, bool adjust) { - bool isPlayer = ptr.getRefData().getHandle() == "player"; + bool isActive = ptr.getRefData().getBaseNode() != 0; + bool isPlayer = isActive && ptr.getRefData().getHandle() == "player"; bool force = true; if (isPlayer) { @@ -271,7 +272,7 @@ RenderingManager::rotateObject( float *f = ptr.getRefData().getPosition().rot; rot.x += f[0], rot.y += f[1], rot.z += f[2]; } - if (!isPlayer) { + if (!isPlayer && isActive) { Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y); Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 923ac484e..79150564e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -558,12 +558,14 @@ namespace MWWorld if (!newCell.isExterior()) { changeToInteriorCell(newCell.cell->name, pos); } else { - changeToExteriorCell(pos); + int cellX = newCell.cell->data.gridX; + int cellY = newCell.cell->data.gridY; + mWorldScene->changeCell(cellX, cellY, pos, false); } } else { - if (!mWorldScene->isCellActive(newCell)) { + if (!mWorldScene->isCellActive(*currCell)) { copyObjectToCell(ptr, newCell, pos); - } else if (!mWorldScene->isCellActive(*currCell)) { + } else if (!mWorldScene->isCellActive(newCell)) { MWWorld::Class::get(ptr).copyToCell(ptr, newCell); mWorldScene->removeObjectFromScene(ptr); mLocalScripts.remove(ptr); @@ -638,10 +640,12 @@ namespace MWWorld float *objRot = ptr.getRefData().getPosition().rot; objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z; - mPhysics->rotateObject( - ptr.getRefData().getHandle(), - ptr.getRefData().getBaseNode()->getOrientation() - ); + if (ptr.getRefData().getBaseNode() != 0) { + mPhysics->rotateObject( + ptr.getRefData().getHandle(), + ptr.getRefData().getBaseNode()->getOrientation() + ); + } } } diff --git a/files/materials/objects.shader b/files/materials/objects.shader index dba239c14..8e5cbf76e 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -116,8 +116,9 @@ shInput(float3, normalPassthrough) shInput(float3, objSpacePositionPassthrough) shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) - //shUniform(float, passIteration) @shAutoConstant(passIteration, pass_iteration_number) + #if !HAS_VERTEXCOLOR shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour) + #endif shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) @shForeach(@shGlobalSettingString(num_lights)) @@ -178,8 +179,13 @@ float3 lightDir; float3 diffuse = float3(0,0,0); float d; + +#if HAS_VERTEXCOLOR + // ambient vertex colour tracking, FFP behaviour + float3 ambient = colourPassthrough.xyz * lightAmbient.xyz; +#else float3 ambient = materialAmbient.xyz * lightAmbient.xyz; - +#endif // shadows only for the first (directional) light #if SHADOWS @@ -237,10 +243,6 @@ #endif @shEndForeach - -#if HAS_VERTEXCOLOR - ambient *= colourPassthrough.xyz; -#endif shOutputColour(0).xyz *= (ambient + diffuse + materialEmissive.xyz); #endif @@ -293,6 +295,7 @@ #if MRT shOutputColour(1) = float4(depthPassthrough / far,1,1,1); #endif + } #endif diff --git a/files/materials/shadows.h b/files/materials/shadows.h index b1dc92d21..65dffe492 100644 --- a/files/materials/shadows.h +++ b/files/materials/shadows.h @@ -1,5 +1,5 @@ -#define FIXED_BIAS 0.005 +#define FIXED_BIAS 0.0003 float depthShadowPCF (shTexture2D shadowMap, float4 shadowMapPos, float2 offset) {