diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 9534ecc904..b12c58f0d4 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -39,7 +39,7 @@ add_openmw_dir (mwscript locals scriptmanager compilercontext interpretercontext cellextensions miscextensions guiextensions soundextensions skyextensions statsextensions containerextensions aiextensions controlextensions extensions globalscripts ref dialogueextensions - animationextensions + animationextensions transformationextensions ) add_openmw_dir (mwsound diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index b2c19ab350..51d0a4f8ef 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -178,6 +178,10 @@ namespace MWBase virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0; + virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0; + + virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z) = 0; + virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) const = 0; ///< Convert cell numbers to position. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index d4f711885c..0d2efcd9ee 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -125,10 +125,14 @@ namespace MWClass void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { + MWWorld::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); + + + std::string headID = ref->base->head; std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; @@ -136,7 +140,8 @@ namespace MWClass std::string smodel = "meshes\\base_anim.nif"; if(beast) smodel = "meshes\\base_animkna.nif"; - physics.insertActorPhysics(ptr, smodel); + physics.insertActorPhysics(ptr, smodel); + MWBase::Environment::get().getMechanicsManager()->addActor (ptr); } @@ -342,4 +347,11 @@ namespace MWClass return weight; } + + void Npc::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const + { + y = 0; + x = 0; + std::cout << "dfdfdfdfnzdofnmqsldgnmqskdhblqkdbv lqksdf"; + } } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 4cb733977e..f50ed2159a 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -76,6 +76,8 @@ namespace MWClass ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. + virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; + static void registerSelf(); }; } diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 98562c053b..41ffd1e930 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -706,7 +706,7 @@ namespace MWDialogue } return false; } - catch (const Compiler::SourceException& error) + catch (const Compiler::SourceException& /* error */) { // error has already been reported via error handler } diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index d20a110093..78eefa338e 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -286,7 +286,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) { object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); } - catch (std::exception& e) + catch (std::exception& /* e */) { return; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index dc57282830..23a96b1d35 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -310,6 +310,9 @@ namespace MWGui && (type != typeid(ESM::Potion).name())) return; + if (MWWorld::Class::get(object).getName(object) == "") // objects without name presented to user can never be picked up + return; + // sound std::string sound = MWWorld::Class::get(object).getUpSoundId(object); MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1); diff --git a/apps/openmw/mwgui/referenceinterface.cpp b/apps/openmw/mwgui/referenceinterface.cpp index f891b3338f..b1f7affb6f 100644 --- a/apps/openmw/mwgui/referenceinterface.cpp +++ b/apps/openmw/mwgui/referenceinterface.cpp @@ -12,6 +12,10 @@ namespace MWGui { } + ReferenceInterface::~ReferenceInterface() + { + } + void ReferenceInterface::checkReferenceAvailable() { if (mPtr.isEmpty()) diff --git a/apps/openmw/mwgui/referenceinterface.hpp b/apps/openmw/mwgui/referenceinterface.hpp index aba9071f3d..39574d0f7a 100644 --- a/apps/openmw/mwgui/referenceinterface.hpp +++ b/apps/openmw/mwgui/referenceinterface.hpp @@ -13,6 +13,7 @@ namespace MWGui { public: ReferenceInterface(); + virtual ~ReferenceInterface(); void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 7920d88a3d..679c7a59eb 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -81,7 +81,7 @@ void ToolTips::onFrame(float frameDuration) { mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); } - catch (std::exception& e) + catch (std::exception /* & e */) { return; } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 8a166eff3a..b979420dd2 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -165,4 +165,9 @@ op 0x2000160: SetFlee op 0x2000161: SetFlee, explicit reference op 0x2000162: SetAlarm op 0x2000163: SetAlarm, explicit reference -opcodes 0x2000164-0x3ffffff unused +op 0x2000164: SetScale +op 0x2000165: SetScale, explicit reference +op 0x2000166: SetAngle +op 0x2000167: SetAngle, explicit reference +opcodes 0x2000168-0x3ffffff unused + diff --git a/apps/openmw/mwscript/extensions.cpp b/apps/openmw/mwscript/extensions.cpp index 1974941461..b7425aca0b 100644 --- a/apps/openmw/mwscript/extensions.cpp +++ b/apps/openmw/mwscript/extensions.cpp @@ -15,6 +15,7 @@ #include "controlextensions.hpp" #include "dialogueextensions.hpp" #include "animationextensions.hpp" +#include "transformationextensions.hpp" namespace MWScript { @@ -31,6 +32,7 @@ namespace MWScript Control::registerExtensions (extensions); Dialogue::registerExtensions (extensions); Animation::registerExtensions (extensions); + Transformation::registerExtensions (extensions); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -47,5 +49,6 @@ namespace MWScript Control::installOpcodes (interpreter); Dialogue::installOpcodes (interpreter); Animation::installOpcodes (interpreter); + Transformation::installOpcodes (interpreter); } } diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 15519b3a6a..4e41ae81d8 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -505,6 +505,7 @@ namespace MWScript } }; + const int numberOfAttributes = 8; const int opcodeGetAttribute = 0x2000027; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp new file mode 100644 index 0000000000..2ea80c0d88 --- /dev/null +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -0,0 +1,140 @@ +#include + +#include + +#include + +#include +#include +#include + +#include "../mwbase/environment.hpp" + +#include "../mwworld/class.hpp" + +#include "interpretercontext.hpp" +#include "ref.hpp" +#include "OgreSceneNode.h" + +namespace MWScript +{ + namespace Transformation + { + template + class OpSetScale : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Float scale = runtime[0].mFloat; + runtime.pop(); + + MWBase::Environment::get().getWorld()->scaleObject(ptr,scale); + } + }; + + template + class OpGetScale : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + runtime.push(ptr.getCellRef().scale); + } + }; + + template + class OpSetAngle : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string axis = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + Interpreter::Type_Float angle = runtime[0].mFloat; + runtime.pop(); + + float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees(); + float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees(); + float az = Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees(); + + if(axis == "X") + { + MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az); + } + if(axis == "Y") + { + MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az); + } + if(axis == "Z") + { + MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle); + } + } + }; + + template + class OpGetAngle : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string axis = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + if(axis == "X") + { + runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees()); + } + if(axis == "Y") + { + runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees()); + } + if(axis == "Z") + { + runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees()); + } + } + }; + + const int opcodeSetScale = 0x2000164; + const int opcodeSetScaleExplicit = 0x2000165; + const int opcodeSetAngle = 0x2000166; + const int opcodeSetAngleExplicit = 0x2000167; + const int opcodeGetScale = 0x2000168; + const int opcodeGetScaleExplicit = 0x2000169; + const int opcodeGetAngle = 0x200016a; + const int opcodeGetAngleExplicit = 0x200016b; + + void registerExtensions (Compiler::Extensions& extensions) + { + extensions.registerInstruction("setscale","f",opcodeSetScale,opcodeSetScaleExplicit); + extensions.registerFunction("getscale",'f',"",opcodeGetScale,opcodeGetScaleExplicit); + extensions.registerInstruction("setangle","Sf",opcodeSetAngle,opcodeSetAngleExplicit); + extensions.registerFunction("getangle",'f',"S",opcodeGetAngle,opcodeGetAngleExplicit); + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + interpreter.installSegment5(opcodeSetScale,new OpSetScale); + interpreter.installSegment5(opcodeSetScaleExplicit,new OpSetScale); + interpreter.installSegment5(opcodeSetAngle,new OpSetAngle); + interpreter.installSegment5(opcodeSetAngleExplicit,new OpSetAngle); + interpreter.installSegment5(opcodeGetScale,new OpGetScale); + interpreter.installSegment5(opcodeGetScaleExplicit,new OpGetScale); + interpreter.installSegment5(opcodeGetAngle,new OpGetAngle); + interpreter.installSegment5(opcodeGetAngleExplicit,new OpGetAngle); + } + } +} diff --git a/apps/openmw/mwscript/transformationextensions.hpp b/apps/openmw/mwscript/transformationextensions.hpp new file mode 100644 index 0000000000..6ee1db1b8e --- /dev/null +++ b/apps/openmw/mwscript/transformationextensions.hpp @@ -0,0 +1,25 @@ +#ifndef GAME_SCRIPT_TRANSFORMATIONEXTENSIONS_H +#define GAME_SCRIPT_TRANSFORMATIONEXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + /// \brief stats-related script functionality (creatures and NPCs) + namespace Transformation + { + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif \ No newline at end of file diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 29563ecc13..c6332d9f32 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -90,7 +90,7 @@ namespace MWSound { if(devname.empty()) throw; - std::cout <<"Failed to open device \""<init(); Settings::Manager::setString("device", "Sound", ""); } diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 74a91f25fd..cd7ebf79a4 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -91,7 +91,7 @@ MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, Ptr::CellS MWWorld::Cells::Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader) : mStore (store), mReader (reader), - mIdCache (20, std::pair ("", 0)), /// \todo make cache size configurable + mIdCache (20, std::pair ("", (Ptr::CellStore*)0)), /// \todo make cache size configurable mIdCacheIndex (0) {} diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 13b40ddbb8..741e3e271f 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -194,4 +194,12 @@ namespace MWWorld { return ""; } + + void Class::adjustScale(const MWWorld::Ptr& ptr,float& scale) const + { + } + + void Class::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const + { + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index fe7b5dc802..20b63a9b95 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -187,6 +187,10 @@ namespace MWWorld virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string /// (default implementation: return empty string) + + virtual void adjustScale(const MWWorld::Ptr& ptr,float& scale) const; + + virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; }; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 4d16a6d1cf..105995aca7 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -165,9 +165,6 @@ namespace MWWorld for (std::vector >::const_iterator iter (actors.begin()); iter!=actors.end(); ++iter) { - OEngine::Physic::PhysicActor* act = mEngine->getCharacter(iter->first); - //if(iter->first == "player") - // std::cout << "This is player\n"; //dirty stuff to get the camera orientation. Must be changed! Ogre::SceneNode *sceneNode = mRender.getScene()->getSceneNode (iter->first); @@ -177,46 +174,28 @@ namespace MWWorld Ogre::Quaternion yawQuat = yawNode->getOrientation(); Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); - // unused - //Ogre::Quaternion both = yawQuat * pitchQuat; - playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); - playerphysics->ps.viewangles.z = 0; - playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; - - if(mFreeFly) - { - Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - pm_ref.rightmove = -dir1.x; - pm_ref.forwardmove = dir1.z; - pm_ref.upmove = dir1.y; + playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); + playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; - //std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n"; - //playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); - //std::cout << "Pitch: " << yawQuat.getPitch() << "Yaw:" << yawQuat.getYaw() << "Roll: " << yawQuat.getRoll() << "\n"; - dir = 0.07*(yawQuat*pitchQuat*dir1); - } - else - { Ogre::Quaternion quat = yawNode->getOrientation(); Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - pm_ref.rightmove = -dir1.x; - pm_ref.forwardmove = dir1.z; - pm_ref.upmove = dir1.y; + pm_ref.rightmove = -iter->second.x; + pm_ref.forwardmove = -iter->second.y; + pm_ref.upmove = iter->second.z; - dir = 0.025*(quat*dir1); } - //set the walk direction - act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y)); - } + + + mEngine->stepSimulation(dt); } @@ -234,10 +213,6 @@ namespace MWWorld if(it->first == "player"){ coord = playerphysics->ps.origin; - //std::cout << "ZCoord: " << coord.z << "\n"; - //std::cout << "Coord" << coord << "\n"; - //coord = Ogre::Vector3(coord.x, coord.z, coord.y); //x, z, -y - } @@ -262,6 +237,7 @@ namespace MWWorld void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh, const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) { + handleToMesh[handle] = mesh; OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle,scale); mEngine->addRigidBody(body); btTransform tr; @@ -314,17 +290,27 @@ namespace MWWorld void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation) { - if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) + if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) { - // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow - // start positions others than 0, 0, 0 act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); } + if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) + { + body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); + } } void PhysicsSystem::scaleObject (const std::string& handle, float scale) { + if(handleToMesh.find(handle) != handleToMesh.end()) + { + btTransform transform = mEngine->getRigidBody(handle)->getWorldTransform(); + removeObject(handle); + Ogre::Quaternion quat = Ogre::Quaternion(transform.getRotation().getW(), transform.getRotation().getX(), transform.getRotation().getY(), transform.getRotation().getZ()); + Ogre::Vector3 vec = Ogre::Vector3(transform.getOrigin().getX(), transform.getOrigin().getY(), transform.getOrigin().getZ()); + addObject(handle, handleToMesh[handle], quat, scale, vec); + } } bool PhysicsSystem::toggleCollisionMode() diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 1a8bd87ae4..b46ce117bf 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -72,6 +72,7 @@ namespace MWWorld OEngine::Physic::PhysicEngine* mEngine; bool mFreeFly; playerMove* playerphysics; + std::map handleToMesh; PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index b1692bd81a..6f6ee93bc6 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -9,6 +9,9 @@ #include "../mwmechanics/drawstate.hpp" +#undef DrawState // How did this get defined again? + // Maybe it's defined by default in every file for windows? + namespace MWBase { class World; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6f9f9936cc..24baac1442 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -597,6 +597,31 @@ namespace MWWorld mPhysics->moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z)); } + void World::scaleObject (const Ptr& ptr, float scale) + { + MWWorld::Class::get(ptr).adjustScale(ptr,scale); + + ptr.getCellRef().scale = scale; + //scale = scale/ptr.getRefData().getBaseNode()->getScale().x; + ptr.getRefData().getBaseNode()->setScale(scale,scale,scale); + mPhysics->scaleObject( ptr.getRefData().getHandle(), scale ); + } + + void World::rotateObject (const Ptr& ptr,float x,float y,float z) + { + MWWorld::Class::get(ptr).adjustRotation(ptr,x,y,z); + + ptr.getRefData().getPosition().rot[0] = Ogre::Degree(x).valueRadians(); + ptr.getRefData().getPosition().rot[1] = Ogre::Degree(y).valueRadians(); + ptr.getRefData().getPosition().rot[2] = Ogre::Degree(z).valueRadians(); + + Ogre::Quaternion rotx(Ogre::Degree(x),Ogre::Vector3::UNIT_X); + Ogre::Quaternion roty(Ogre::Degree(y),Ogre::Vector3::UNIT_Y); + Ogre::Quaternion rotz(Ogre::Degree(z),Ogre::Vector3::UNIT_Z); + ptr.getRefData().getBaseNode()->setOrientation(rotz*roty*rotx); + mPhysics->rotateObject(ptr.getRefData().getHandle(),ptr.getRefData().getBaseNode()->getOrientation()); + } + void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const { const int cellSize = 8192; diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index d64b3a373b..8b39a78f1f 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -188,7 +188,7 @@ namespace MWWorld virtual bool toggleSky(); ///< \return Resulting mode - virtual void changeWeather (const std::string& region, const unsigned int id); + virtual void changeWeather (const std::string& region, unsigned int id); virtual int getCurrentWeather() const; @@ -219,6 +219,10 @@ namespace MWWorld virtual void moveObject (const Ptr& ptr, float x, float y, float z); + virtual void scaleObject (const Ptr& ptr, float scale); + + virtual void rotateObject (const Ptr& ptr,float x,float y,float z); + virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) const; ///< Convert cell numbers to position. diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index d3b75d4ae4..e9ce3f6150 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -73,14 +73,16 @@ class DirArchive: public Ogre::FileSystemArchive { { String passed = filename; - if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' + if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') + passed = filename.substr(0, filename.length() - 6); + else if(filename.at(filename.length() - 2) == '"') + passed = filename.substr(0, filename.length() - 9); + else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' || filename.at(filename.length() - 1) == '|') - { passed = filename.substr(0, filename.length() - 2); - } - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); + + copy = passed; } @@ -226,14 +228,16 @@ public: BSAFile *narc = (BSAFile*)&arc; String passed = filename; - if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' + if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') + passed = filename.substr(0, filename.length() - 6); + else if(filename.at(filename.length() - 2) == '"') + passed = filename.substr(0, filename.length() - 9); + else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' || filename.at(filename.length() - 1) == '|') - { passed = filename.substr(0, filename.length() - 2); - } - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); + + // Open the file StreamPtr strm = narc->getFile(passed.c_str()); @@ -248,14 +252,16 @@ bool exists(const String& filename) { // Check if the file exists. bool cexists(const String& filename) const { String passed = filename; - if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' + if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') + passed = filename.substr(0, filename.length() - 6); + else if(filename.at(filename.length() - 2) == '"') + passed = filename.substr(0, filename.length() - 9); + else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' || filename.at(filename.length() - 1) == '|') - { passed = filename.substr(0, filename.length() - 2); - } - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); + + return arc.exists(passed.c_str()); } diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index 41bc3b0a0d..4105c4c790 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -1,4 +1,4 @@ -/* + /* OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > @@ -45,18 +45,11 @@ typedef unsigned char ubyte; using namespace NifBullet; + ManualBulletShapeLoader::~ManualBulletShapeLoader() { } -Ogre::Matrix3 ManualBulletShapeLoader::getMatrix(Nif::Transformation* tr) -{ - return tr->rotation; -} -Ogre::Vector3 ManualBulletShapeLoader::getVector(Nif::Transformation* tr) -{ - return tr->pos; -} btQuaternion ManualBulletShapeLoader::getbtQuat(Ogre::Matrix3 &m) { @@ -109,15 +102,15 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) bool hasCollisionNode = hasRootCollisionNode(node); //do a first pass - handleNode(node,0,Ogre::Matrix3::IDENTITY,Ogre::Vector3::ZERO,1,hasCollisionNode,false,false); + handleNode(node,0,NULL,hasCollisionNode,false,false); //if collide = false, then it does a second pass which create a shape for raycasting. if(cShape->collide == false) { - handleNode(node,0,Ogre::Matrix3::IDENTITY,Ogre::Vector3::ZERO,1,hasCollisionNode,false,true); + handleNode(node,0,NULL,hasCollisionNode,false,true); } - cShape->collide = hasCollisionNode&&cShape->collide; + //cShape->collide = hasCollisionNode&&cShape->collide; struct TriangleMeshShape : public btBvhTriangleMeshShape { @@ -164,8 +157,9 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node) } void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, - Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly) + const Nif::Transformation *trafo,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly) { + // Accumulate the flags from all the child nodes. This works for all // the flags we currently use, at least. flags |= node->flags; @@ -199,18 +193,26 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, } } - //transfo of parents node + curent node - Ogre::Matrix3 finalRot; - Ogre::Vector3 finalPos; - float finalScale; - Nif::Transformation &final = node->trafo; - Ogre::Vector3 nodePos = getVector(&final); - Ogre::Matrix3 nodeRot = getMatrix(&final); + if (trafo) + { - finalPos = nodePos + parentPos; - finalRot = parentRot*nodeRot; - finalScale = final.scale*parentScale; + // Get a non-const reference to the node's data, since we're + // overwriting it. TODO: Is this necessary? + Nif::Transformation &final = node->trafo; + + // For both position and rotation we have that: + // final_vector = old_vector + old_rotation*new_vector*old_scale + final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale; + final.velocity = trafo->velocity + trafo->rotation*final.velocity*trafo->scale; + + // Merge the rotations together + final.rotation = trafo->rotation * final.rotation; + + // Scale + final.scale *= trafo->scale; + + } // For NiNodes, loop through children @@ -222,14 +224,14 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, { if (list.has(i)) { - handleNode(&list[i], flags,finalRot,finalPos,finalScale,hasCollisionNode,isCollisionNode,raycastingOnly); + handleNode(&list[i], flags,&node->trafo,hasCollisionNode,isCollisionNode,raycastingOnly); } } } - else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode)) + else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode)) { cShape->collide = true; - handleNiTriShape(dynamic_cast(node), flags,finalRot,finalPos,parentScale,raycastingOnly); + handleNiTriShape(dynamic_cast(node), flags,node->trafo.rotation,node->trafo.pos,node->trafo.scale,raycastingOnly); } else if(node->recType == Nif::RC_RootCollisionNode) { @@ -238,7 +240,7 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, for (int i=0; itrafo, hasCollisionNode,true,raycastingOnly); } } } @@ -270,17 +272,19 @@ void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape *shape, int flags Nif::NiTriShapeData *data = shape->data.getPtr(); - float* vertices = (float*)&data->vertices[0]; - unsigned short* triangles = (unsigned short*)&data->triangles[0]; - + float* vertices = &data->vertices[0]; + short* triangles = &data->triangles[0]; + const Ogre::Matrix3 &rot = shape->trafo.rotation; + const Ogre::Vector3 &pos = shape->trafo.pos; + float scale = shape->trafo.scale; for(unsigned int i=0; i < data->triangles.size(); i = i+3) { Ogre::Vector3 b1(vertices[triangles[i+0]*3]*parentScale,vertices[triangles[i+0]*3+1]*parentScale,vertices[triangles[i+0]*3+2]*parentScale); Ogre::Vector3 b2(vertices[triangles[i+1]*3]*parentScale,vertices[triangles[i+1]*3+1]*parentScale,vertices[triangles[i+1]*3+2]*parentScale); Ogre::Vector3 b3(vertices[triangles[i+2]*3]*parentScale,vertices[triangles[i+2]*3+1]*parentScale,vertices[triangles[i+2]*3+2]*parentScale); - b1 = parentRot * b1 + parentPos; - b2 = parentRot * b2 + parentPos; - b3 = parentRot * b3 + parentPos; + b1 = pos + rot*b1*scale; + b2 = pos + rot*b2*scale; + b3 = pos + rot*b3*scale; mTriMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z)); } } diff --git a/components/nifbullet/bullet_nif_loader.hpp b/components/nifbullet/bullet_nif_loader.hpp index bf288e0811..b2f0233018 100644 --- a/components/nifbullet/bullet_nif_loader.hpp +++ b/components/nifbullet/bullet_nif_loader.hpp @@ -85,10 +85,6 @@ public: void load(const std::string &name,const std::string &group); private: - Ogre::Matrix3 getMatrix(Nif::Transformation* tr); - - Ogre::Vector3 getVector(Nif::Transformation* tr); - btQuaternion getbtQuat(Ogre::Matrix3 &m); btVector3 getbtVector(Ogre::Vector3 &v); @@ -97,10 +93,10 @@ private: *Parse a node. */ void handleNode(Nif::Node *node, int flags, - Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly); + const Nif::Transformation *trafo, bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly); /** - *Helpler function + *Helper function */ bool hasRootCollisionNode(Nif::Node* node); diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index ad604c8d4a..aca1966b92 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1252,7 +1252,7 @@ void NIFLoader::loadResource(Ogre::Resource *resource) // Look it up resourceName = mesh->getName(); - //std::cout << resourceName << "\n"; + // Helper that computes bounding boxes for us. BoundsFinder bounds; diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 500e8a7efa..11c18010ea 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -333,11 +333,18 @@ namespace Physic RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) { + char uniqueID[8]; + sprintf( uniqueID, "%07.3f", scale ); + std::string sid = uniqueID; + std::string outputstring = mesh + uniqueID + "\"|"; + //std::cout << "The string" << outputstring << "\n"; + //get the shape from the .nif - mShapeLoader->load(mesh,"General"); - BulletShapeManager::getSingletonPtr()->load(mesh,"General"); - BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General"); - shape->Shape->setLocalScaling(btVector3(scale,scale,scale)); + mShapeLoader->load(outputstring,"General"); + BulletShapeManager::getSingletonPtr()->load(outputstring,"General"); + BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General"); + shape->Shape->setLocalScaling( btVector3(scale,scale,scale)); + //btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(dynamic_cast (shape->Shape), btVector3(scale,scale,scale)); //create the motionState CMotionState* newMotionState = new CMotionState(this,name); @@ -400,18 +407,32 @@ namespace Physic if (it != RigidBodyMap.end() ) { RigidBody* body = it->second; + //btScaledBvhTriangleMeshShape* scaled = dynamic_cast (body->getCollisionShape()); + if(body != NULL) { delete body; } + /*if(scaled != NULL) + { + delete scaled; + }*/ RigidBodyMap.erase(it); } } RigidBody* PhysicEngine::getRigidBody(std::string name) { - RigidBody* body = RigidBodyMap[name]; - return body; + RigidBodyContainer::iterator it = RigidBodyMap.find(name); + if (it != RigidBodyMap.end() ) + { + RigidBody* body = RigidBodyMap[name]; + return body; + } + else + { + return 0; + } } void PhysicEngine::stepSimulation(double deltaT) @@ -468,8 +489,16 @@ namespace Physic PhysicActor* PhysicEngine::getCharacter(std::string name) { - PhysicActor* act = PhysicActorMap[name]; - return act; + PhysicActorContainer::iterator it = PhysicActorMap.find(name); + if (it != PhysicActorMap.end() ) + { + PhysicActor* act = PhysicActorMap[name]; + return act; + } + else + { + return 0; + } } void PhysicEngine::emptyEventLists(void) diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index e327f24e15..3988c75a4f 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -7,6 +7,7 @@ #include #include #include "BulletShapeLoader.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" class btRigidBody; class btBroadphaseInterface; diff --git a/libs/openengine/bullet/pmove.cpp b/libs/openengine/bullet/pmove.cpp index b723f67e47..e13e9e6c07 100644 --- a/libs/openengine/bullet/pmove.cpp +++ b/libs/openengine/bullet/pmove.cpp @@ -229,7 +229,7 @@ bool PM_SlideMove( bool gravity ) end = pm->ps.origin + pm->ps.velocity * time_left; // see if we can make it there - //pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask); + //pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemaskg); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj); newtrace(&trace, pm->ps.origin, end, halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine); @@ -274,7 +274,7 @@ bool PM_SlideMove( bool gravity ) { // pm->ps->velocity += (trace.plane.normal + pm->ps->velocity) //VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity ); - pm->ps.velocity = (trace.planenormal + pm->ps.velocity); + pm->ps.velocity = trace.planenormal + pm->ps.velocity; break; } } @@ -298,6 +298,12 @@ bool PM_SlideMove( bool gravity ) if ( into >= 0.1 ) continue; // move doesn't interact with the plane + + if(planes[i].x >= .70) + { + pm->ps.velocity = Ogre::Vector3(0,0,0); + return true; + } // see how hard we are hitting things if ( -into > pml.impactSpeed ) pml.impactSpeed = -into; @@ -318,6 +324,13 @@ bool PM_SlideMove( bool gravity ) if (clipVelocity.dotProduct(planes[j]) >= 0.1) //if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) continue; // move doesn't interact with the plane + + + + + //pm->ps.velocity = Ogre::Vector3(0,0,0); + //return true; + // try clipping the move to the plane PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP ); @@ -327,8 +340,8 @@ bool PM_SlideMove( bool gravity ) if (clipVelocity.dotProduct(planes[i]) >= 0) //if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) continue; - - + + // slide the original velocity along the crease //dProduct (planes[i], planes[j], dir); dir = planes[i].crossProduct(planes[j]) ; @@ -360,6 +373,7 @@ bool PM_SlideMove( bool gravity ) // see if there is a third plane the the new move enters for ( k = 0 ; k < numplanes ; k++ ) { + if ( k == i || k == j ) continue; @@ -513,7 +527,7 @@ int PM_StepSlideMove( bool gravity ) delta = pm->ps.origin.z - start_o.z; if ( delta > 2 ) { - pm->ps.counter = 10; + pm->ps.counter = 5; /* if (gravity) @@ -844,6 +858,8 @@ static void PM_WalkMove( playerMove* const pmove ) float accelerate; float vel; //pm->ps.gravity = 4000; + + //std::cout << "Player is walking\n"; if ( pm->ps.waterlevel > 2 && //DotProduct( pml.forward, pml.groundTrace.plane.normal ) > 0 ) pml.forward.dotProduct(pml.groundTrace.planenormal) > 0.0f) @@ -1145,6 +1161,10 @@ void PM_GroundTraceMissed() { traceResults trace; Ogre::Vector3 point; + //We should not have significant upwards velocity when in the air, unless we jumped. + //This code protects against flying into the air when moving at high speeds. + //Z velocity is set to 50, instead of 0, to help move up certain steps. + //std::cout << "Ground trace missed\n"; // we just transitioned into freefall //if ( pm->debugLevel ) @@ -1407,10 +1427,13 @@ static void PM_GroundTrace( void ) // if the trace didn't hit anything, we are in free fall if ( trace.fraction == 1.0) { + if(pm->ps.velocity.z > 50.0f && pm->ps.bSnap && pm->ps.speed > 1000.0f) + pm->ps.velocity.z = 50.0f; if(pm->ps.snappingImplemented){ if(pm->ps.bSnap && pm->ps.counter <= 0) PM_GroundTraceMissed(); } + return; @@ -1457,6 +1480,7 @@ static void PM_GroundTrace( void ) // slopes that are too steep will not be considered onground //if ( trace.plane.normal[2] < MIN_WALK_NORMAL ) + //std::cout << "MinWalkNormal" << trace.planenormal.z; if (trace.planenormal.z < MIN_WALK_NORMAL) { //if ( pm->debugLevel ) @@ -1569,8 +1593,11 @@ void PM_AirMove() else PM_SlideMove ( qtrue ); #endif*/ + //std::cout << "Moving in the air" << pm->ps.velocity << "\n"; /*bprintf("%i ", */PM_StepSlideMove ( true )/* )*/; + + } static void PM_NoclipMove( void ) diff --git a/libs/openengine/bullet/pmove.h b/libs/openengine/bullet/pmove.h index 0fdb8f0d8d..aea63d1dbd 100644 --- a/libs/openengine/bullet/pmove.h +++ b/libs/openengine/bullet/pmove.h @@ -28,7 +28,7 @@ static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2); #define MAX_CLIP_PLANES 5 #define OVERCLIP 1.001f //#define STEPSIZE 18 // 18 is way too much -#define STEPSIZE (18 / 2) +#define STEPSIZE (9) #ifndef M_PI #define M_PI 3.14159265358979323846f #endif @@ -41,7 +41,7 @@ static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2); #define MAX_GENTITIES (1 << GENTITYNUM_BITS) #define ENTITYNUM_NONE (MAX_GENTITIES - 1) #define ENTITYNUM_WORLD (MAX_GENTITIES - 2) -#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes +#define MIN_WALK_NORMAL .7f // can't walk on very steep slopes #define JUMP_VELOCITY (270) #define PS_PMOVEFRAMECOUNTBITS 6 #define MINS_Z -24