Merge remote-tracking branch 'glorf/rotate-update1'

actorid
Marc Zinnschlag 12 years ago
commit 1e9656ee9c

@ -230,6 +230,8 @@ namespace MWBase
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0;
virtual void localRotateObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos) = 0;
///< place an object in a "safe" location (ie not in the void, etc).

@ -318,5 +318,9 @@ op 0x20001fb: DropSoulGem, explicit reference
op 0x20001fc: OnDeath
op 0x20001fd: IsWerewolf
op 0x20001fe: IsWerewolf, explicit reference
op 0x20001ff: Rotate
op 0x2000200: Rotate, explicit reference
op 0x2000201: RotateWorld
op 0x2000202: RotateWorld, explicit reference
opcodes 0x20001ff-0x3ffffff unused
opcodes 0x2000203-0x3ffffff unused

@ -84,21 +84,27 @@ namespace MWScript
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();
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
float *objRot = ptr.getRefData().getPosition().rot;
float lx = Ogre::Radian(objRot[0]).valueDegrees();
float ly = Ogre::Radian(objRot[1]).valueDegrees();
float lz = Ogre::Radian(objRot[2]).valueDegrees();
if (axis == "x")
{
MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az);
MWBase::Environment::get().getWorld()->localRotateObject(ptr,angle-lx,ay,az);
}
else if (axis == "y")
{
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az);
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,angle-ly,az);
}
else if (axis == "z")
{
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle);
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,ay,angle-lz);
}
else
throw std::runtime_error ("invalid ration axis: " + axis);
@ -148,15 +154,15 @@ namespace MWScript
if (axis=="x")
{
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees());
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[0]).valueDegrees()+Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees());
}
else if (axis=="y")
{
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees());
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[1]).valueDegrees()+Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees());
}
else if (axis=="z")
{
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees());
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[2]).valueDegrees()+Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees());
}
else
throw std::runtime_error ("invalid ration axis: " + axis);
@ -542,6 +548,78 @@ namespace MWScript
}
};
template<class R>
class OpRotate : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
const MWWorld::Ptr& ptr = R()(runtime);
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Float rotation = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
runtime.pop();
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
if (axis == "x")
{
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax+rotation,ay,az);
}
else if (axis == "y")
{
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,ay+rotation,az);
}
else if (axis == "z")
{
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,ay,az+rotation);
}
else
throw std::runtime_error ("invalid ration axis: " + axis);
}
};
template<class R>
class OpRotateWorld : 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 rotation = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
runtime.pop();
float *objRot = ptr.getRefData().getPosition().rot;
float ax = Ogre::Radian(objRot[0]).valueDegrees();
float ay = Ogre::Radian(objRot[1]).valueDegrees();
float az = Ogre::Radian(objRot[2]).valueDegrees();
if (axis == "x")
{
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax+rotation,ay,az);
}
else if (axis == "y")
{
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay+rotation,az);
}
else if (axis == "z")
{
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,az+rotation);
}
else
throw std::runtime_error ("invalid rotation axis: " + axis);
}
};
const int opcodeSetScale = 0x2000164;
const int opcodeSetScaleExplicit = 0x2000165;
const int opcodeSetAngle = 0x2000166;
@ -568,6 +646,10 @@ namespace MWScript
const int opcodePlaceAtMeExplicit = 0x200019e;
const int opcodeModScale = 0x20001e3;
const int opcodeModScaleExplicit = 0x20001e4;
const int opcodeRotate = 0x20001ff;
const int opcodeRotateExplicit = 0x2000200;
const int opcodeRotateWorld = 0x2000201;
const int opcodeRotateWorldExplicit = 0x2000202;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -585,6 +667,8 @@ namespace MWScript
extensions.registerInstruction("placeatpc","clfl",opcodePlaceAtPc);
extensions.registerInstruction("placeatme","clfl",opcodePlaceAtMe,opcodePlaceAtMeExplicit);
extensions.registerInstruction("modscale","f",opcodeModScale,opcodeModScaleExplicit);
extensions.registerInstruction("rotate","cf",opcodeRotate,opcodeRotateExplicit);
extensions.registerInstruction("rotateworld","cf",opcodeRotateWorld,opcodeRotateWorldExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -614,6 +698,10 @@ namespace MWScript
interpreter.installSegment5(opcodePlaceAtMeExplicit,new OpPlaceAtMe<ExplicitRef>);
interpreter.installSegment5(opcodeModScale,new OpModScale<ImplicitRef>);
interpreter.installSegment5(opcodeModScaleExplicit,new OpModScale<ExplicitRef>);
interpreter.installSegment5(opcodeRotate,new OpRotate<ImplicitRef>);
interpreter.installSegment5(opcodeRotateExplicit,new OpRotate<ExplicitRef>);
interpreter.installSegment5(opcodeRotateWorld,new OpRotateWorld<ImplicitRef>);
interpreter.installSegment5(opcodeRotateWorldExplicit,new OpRotateWorld<ExplicitRef>);
}
}
}

@ -19,6 +19,7 @@ namespace MWWorld
mEnabled = refData.mEnabled;
mCount = refData.mCount;
mPosition = refData.mPosition;
mLocalRotation = refData.mLocalRotation;
mCustomData = refData.mCustomData ? refData.mCustomData->clone() : 0;
}
@ -34,7 +35,11 @@ namespace MWWorld
RefData::RefData (const ESM::CellRef& cellRef)
: mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mPosition (cellRef.mPos),
mCustomData (0)
{}
{
mLocalRotation.rot[0]=0;
mLocalRotation.rot[1]=0;
mLocalRotation.rot[2]=0;
}
RefData::RefData (const RefData& refData)
: mBaseNode(0), mCustomData (0)
@ -141,6 +146,11 @@ namespace MWWorld
return mPosition;
}
LocalRotation& RefData::getLocalRotation()
{
return mLocalRotation;
}
void RefData::setCustomData (CustomData *data)
{
delete mCustomData;

@ -18,6 +18,10 @@ namespace ESM
namespace MWWorld
{
struct LocalRotation{
float rot[3];
};
class CustomData;
class RefData
@ -34,6 +38,8 @@ namespace MWWorld
ESM::Position mPosition;
LocalRotation mLocalRotation;
CustomData *mCustomData;
void copy (const RefData& refData);
@ -78,6 +84,8 @@ namespace MWWorld
ESM::Position& getPosition();
LocalRotation& getLocalRotation();
void setCustomData (CustomData *data);
///< Set custom data (potentially replacing old custom data). The ownership of \æ data is
/// transferred to this.

@ -49,7 +49,12 @@ namespace
{
rendering.addObject(ptr);
class_.insertObject(ptr, physics);
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
MWBase::Environment::get().getWorld()->localRotateObject(ptr, ax, ay, az);
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().mScale);
class_.adjustPosition(ptr);
}

@ -824,6 +824,29 @@ namespace MWWorld
}
}
void World::localRotateObject (const Ptr& ptr, float x, float y, float z)
{
if (ptr.getRefData().getBaseNode() != 0) {
ptr.getRefData().getLocalRotation().rot[0]=Ogre::Degree(x).valueRadians();
ptr.getRefData().getLocalRotation().rot[1]=Ogre::Degree(y).valueRadians();
ptr.getRefData().getLocalRotation().rot[2]=Ogre::Degree(z).valueRadians();
float *worldRot = ptr.getRefData().getPosition().rot;
Ogre::Quaternion worldRotQuat(Ogre::Quaternion(Ogre::Radian(-worldRot[0]), Ogre::Vector3::UNIT_X)*
Ogre::Quaternion(Ogre::Radian(-worldRot[1]), Ogre::Vector3::UNIT_Y)*
Ogre::Quaternion(Ogre::Radian(-worldRot[2]), Ogre::Vector3::UNIT_Z));
Ogre::Quaternion rot(Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-x).valueRadians()), Ogre::Vector3::UNIT_X)*
Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-y).valueRadians()), Ogre::Vector3::UNIT_Y)*
Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-z).valueRadians()), Ogre::Vector3::UNIT_Z));
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot);
mPhysics->rotateObject(ptr);
}
}
void World::adjustPosition(const Ptr &ptr)
{
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos[0], ptr.getRefData().getPosition().pos[1], ptr.getRefData().getPosition().pos[2]);

@ -254,6 +254,8 @@ namespace MWWorld
/// \param adjust indicates rotation should be set or adjusted
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
virtual void localRotateObject (const Ptr& ptr, float x, float y, float z);
virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos);
///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr.

Loading…
Cancel
Save