mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-06 00:55:50 +00:00
205 lines
6.4 KiB
C++
205 lines
6.4 KiB
C++
#ifndef OPENMW_MWPHYSICS_ACTOR_H
|
|
#define OPENMW_MWPHYSICS_ACTOR_H
|
|
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
#include "ptrholder.hpp"
|
|
|
|
#include <components/detournavigator/collisionshapetype.hpp>
|
|
|
|
#include <LinearMath/btTransform.h>
|
|
#include <osg/Quat>
|
|
#include <osg/Vec3f>
|
|
|
|
class btCollisionShape;
|
|
class btCollisionObject;
|
|
class btCollisionWorld;
|
|
class btConvexShape;
|
|
|
|
namespace Resource
|
|
{
|
|
struct BulletShape;
|
|
}
|
|
|
|
namespace MWPhysics
|
|
{
|
|
class PhysicsTaskScheduler;
|
|
|
|
class Actor final : public PtrHolder
|
|
{
|
|
public:
|
|
Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler,
|
|
bool canWaterWalk, DetourNavigator::CollisionShapeType collisionShapeType);
|
|
~Actor() override;
|
|
|
|
Actor(const Actor&) = delete;
|
|
|
|
Actor& operator=(const Actor&) = delete;
|
|
|
|
/**
|
|
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
|
|
*/
|
|
void enableCollisionMode(bool collision);
|
|
|
|
bool getCollisionMode() const { return mInternalCollisionMode; }
|
|
|
|
btConvexShape* getConvexShape() const { return mConvexShape; }
|
|
|
|
/**
|
|
* Enables or disables the *external* collision body. If disabled, other actors will not collide with this
|
|
* actor.
|
|
*/
|
|
void enableCollisionBody(bool collision);
|
|
|
|
void updateScale();
|
|
void setRotation(osg::Quat quat);
|
|
|
|
/**
|
|
* Return true if the collision shape looks the same no matter how its Z rotated.
|
|
*/
|
|
bool isRotationallyInvariant() const;
|
|
|
|
/**
|
|
* Used by the physics simulation to store the simulation result. Used in conjunction with mWorldPosition
|
|
* to account for e.g. scripted movements
|
|
*/
|
|
void setSimulationPosition(const osg::Vec3f& position);
|
|
|
|
void updateCollisionObjectPosition();
|
|
|
|
/**
|
|
* Returns the half extents of the collision body (scaled according to collision scale)
|
|
*/
|
|
osg::Vec3f getHalfExtents() const;
|
|
|
|
/**
|
|
* Returns the half extents of the collision body (not scaled)
|
|
*/
|
|
osg::Vec3f getOriginalHalfExtents() const;
|
|
|
|
/**
|
|
* Returns the position of the collision body
|
|
* @note The collision shape's origin is in its center, so the position returned can be described as center of
|
|
* the actor collision box in world space.
|
|
*/
|
|
osg::Vec3f getCollisionObjectPosition() const;
|
|
|
|
/**
|
|
* Store the current position into mPreviousPosition, then move to this position.
|
|
* Returns true if the new position is different.
|
|
*/
|
|
bool setPosition(const osg::Vec3f& position);
|
|
|
|
// force set actor position to be as in Ptr::RefData
|
|
void updatePosition();
|
|
|
|
// register a position offset that will be applied during simulation.
|
|
void adjustPosition(const osg::Vec3f& offset);
|
|
|
|
// apply position offset. Can't be called during simulation
|
|
void applyOffsetChange();
|
|
|
|
/**
|
|
* Returns the half extents of the collision body (scaled according to rendering scale)
|
|
* @note The reason we need this extra method is because of an inconsistency in MW - NPC race scales aren't
|
|
* applied to the collision shape, most likely to make environment collision testing easier. However in some
|
|
* cases (swimming level) we want the actual scale.
|
|
*/
|
|
osg::Vec3f getRenderingHalfExtents() const;
|
|
|
|
/**
|
|
* Sets the current amount of inertial force (incl. gravity) affecting this physic actor
|
|
*/
|
|
void setInertialForce(const osg::Vec3f& force);
|
|
|
|
/**
|
|
* Gets the current amount of inertial force (incl. gravity) affecting this physic actor
|
|
*/
|
|
const osg::Vec3f& getInertialForce() const { return mForce; }
|
|
|
|
void setOnGround(bool grounded);
|
|
|
|
bool getOnGround() const { return mOnGround; }
|
|
|
|
void setOnSlope(bool slope);
|
|
|
|
bool getOnSlope() const { return mOnSlope; }
|
|
|
|
/// Sets whether this actor should be able to collide with the water surface
|
|
void setCanWaterWalk(bool waterWalk);
|
|
|
|
/// Sets whether this actor has been walking on the water surface in the last frame
|
|
void setWalkingOnWater(bool walkingOnWater);
|
|
bool isWalkingOnWater() const;
|
|
|
|
MWWorld::Ptr getStandingOnPtr() const;
|
|
void setStandingOnPtr(const MWWorld::Ptr& ptr);
|
|
|
|
unsigned int getStuckFrames() const { return mStuckFrames; }
|
|
void setStuckFrames(unsigned int frames) { mStuckFrames = frames; }
|
|
|
|
const osg::Vec3f& getLastStuckPosition() const { return mLastStuckPosition; }
|
|
void setLastStuckPosition(osg::Vec3f position) { mLastStuckPosition = position; }
|
|
|
|
bool canMoveToWaterSurface(float waterlevel, const btCollisionWorld* world) const;
|
|
|
|
bool isActive() const { return mActive; }
|
|
|
|
void setActive(bool value) { mActive = value; }
|
|
|
|
DetourNavigator::CollisionShapeType getCollisionShapeType() const { return mCollisionShapeType; }
|
|
|
|
private:
|
|
MWWorld::Ptr mStandingOnPtr;
|
|
/// Removes then re-adds the collision object to the dynamics world
|
|
void updateCollisionMask();
|
|
void addCollisionMask(int collisionMask);
|
|
int getCollisionMask() const;
|
|
|
|
/// Returns the mesh translation, scaled and rotated as necessary
|
|
osg::Vec3f getScaledMeshTranslation() const;
|
|
|
|
bool mCanWaterWalk;
|
|
bool mWalkingOnWater;
|
|
|
|
bool mRotationallyInvariant;
|
|
|
|
DetourNavigator::CollisionShapeType mCollisionShapeType;
|
|
|
|
std::unique_ptr<btCollisionShape> mShape;
|
|
btConvexShape* mConvexShape;
|
|
|
|
osg::Vec3f mMeshTranslation;
|
|
osg::Vec3f mOriginalHalfExtents;
|
|
osg::Vec3f mHalfExtents;
|
|
osg::Vec3f mRenderingHalfExtents;
|
|
osg::Quat mRotation;
|
|
|
|
osg::Vec3f mScale;
|
|
osg::Vec3f mPositionOffset;
|
|
bool mWorldPositionChanged = false;
|
|
bool mSkipSimulation = true;
|
|
mutable std::mutex mPositionMutex;
|
|
|
|
unsigned int mStuckFrames;
|
|
osg::Vec3f mLastStuckPosition;
|
|
|
|
osg::Vec3f mForce;
|
|
bool mOnGround;
|
|
bool mOnSlope;
|
|
bool mInternalCollisionMode;
|
|
bool mExternalCollisionMode;
|
|
bool mActive;
|
|
|
|
PhysicsTaskScheduler* mTaskScheduler;
|
|
|
|
inline void updateScaleUnsafe();
|
|
|
|
inline void updateCollisionObjectPositionUnsafe();
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|