#pragma once #include "entity.h" #include "motion.h" class Mover__SharedData; class Mover; class CollisionAssistant; class BoundingBoxTreeNode; class BoxedSolid; class BoxedSolidCollision; class BoxedSolidCollisionList; class Normal; class Line; class Environment; //########################################################################## //#################### Mover::UpdateMessage ########################## //########################################################################## struct Mover__UpdateRecord: public Entity::UpdateRecord { public: Motion localVelocity, localAcceleration; Vector3D worldLinearVelocity, worldLinearAcceleration; }; //########################################################################## //##################### Mover::MakeMessage ########################## //########################################################################## class Mover__MakeMessage: public Entity::MakeMessage { public: Motion localVelocity, localAcceleration; Mover__MakeMessage( Receiver::MessageID message_ID, size_t length, Entity::ClassID class_ID, const EntityID &owner_ID, ResourceDescription::ResourceID resource_ID, LWord instance_flags, const Origin &origin, const Motion &velocity, const Motion &acceleration ): Entity::MakeMessage( message_ID, length, class_ID, owner_ID, resource_ID, instance_flags, origin ), localVelocity(velocity), localAcceleration(acceleration) {} Mover__MakeMessage( Receiver::MessageID message_ID, size_t length, const EntityID &entity_ID, Entity::ClassID class_ID, const EntityID &owner_ID, ResourceDescription::ResourceID resource_ID, LWord instance_flags, const Origin &origin, const Motion &velocity, const Motion &acceleration ): Entity::MakeMessage( message_ID, length, entity_ID, class_ID, owner_ID, resource_ID, instance_flags, origin ), localVelocity(velocity), localAcceleration(acceleration) {} }; //########################################################################## //##################### Mover::ModelResource ######################### //########################################################################## struct Mover__ModelResource { Scalar moverMass; Vector3D momentOfInertia, positiveLinearDragCoefficients, negativeLinearDragCoefficients, angularDragCoefficients; Scalar frictionCoefficient, elasticityCoefficient, minimumBounceSpeed; }; //########################################################################## //############################ Mover ################################# //########################################################################## class Mover: public Entity { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Shared Data support // public: static Derivation *GetClassDerivations(); static SharedData DefaultData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Attribute Support // public: enum { LocalVelocityAttributeID = Entity::NextAttributeID, LocalAccelerationAttributeID, WorldLinearVelocityAttributeID, WorldLinearAccelerationAttributeID, MoverMassAttributeID, MomentOfInertiaAttributeID, PositiveLinearDragCoefficientsAttributeID, NegativeLinearDragCoefficientsAttributeID, AngularDragCoefficientsAttributeID, FrictionCoefficientAttributeID, ElasticityCoefficientAttributeID, MinimumBounceSpeedAttributeID, NextAttributeID }; private: static const IndexEntry AttributePointers[]; protected: //static AttributeIndexSet AttributeIndex static AttributeIndexSet& GetAttributeIndex(); // // public attribute declarations go here // public: Motion localVelocity, localAcceleration; Vector3D worldLinearVelocity, worldLinearAcceleration; Scalar moverMass; Vector3D momentOfInertia, positiveLinearDragCoefficients, negativeLinearDragCoefficients, angularDragCoefficients; Scalar frictionCoefficient, elasticityCoefficient, minimumBounceSpeed; // // virtual access // public: virtual Vector3D GetWorldLinearVelocity() {return worldLinearVelocity;} virtual Vector3D GetWorldLinearAcceleration() {return worldLinearAcceleration;} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Model Support // public: enum { StasisState = Entity::StateCount, StateCount }; typedef Mover__UpdateRecord UpdateRecord; typedef Mover__MakeMessage MakeMessage; typedef void (Mover::*Performance)(Scalar time_slice); void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } void UpdateWorldMotion(); void UpdateLocalMotion(); void ApplyWorldAccelerations(Scalar time_slice); void ApplyAirResistanceAndGravity(Scalar power=1.0f); void CalculateDrag( Vector3D *drag, const Vector3D &velocity, const Vector3D &positive_CODs, const Vector3D &negative_CODs, Scalar power ); void ApplyLocalForce( const Vector3D &force, const Vector3D &moment ); void ApplyLocalAcceleration( const Vector3D &acceleration, const Vector3D &moment ); Environment* GetEnvironment() {Check(this); return localEnvironment;} typedef Logical (Mover::*DeadReckoner)(); void SetDeadReckoner(DeadReckoner reckoner) {Check(this); deadReckoner = reckoner;} Logical NoDeadReckoner(); Logical LinearDeadReckoner(); Logical AcceleratedDeadReckoner(); void DeadReckon(Scalar time_slice); protected: void WriteUpdateRecord( Simulation::UpdateRecord *message, int update_model ); void ReadUpdateRecord(Simulation::UpdateRecord *message); void PerformAndWatch( const Time& till, MemoryStream *update_stream ); int normalizeCount; Environment *localEnvironment; DeadReckoner deadReckoner; Origin projectedOrigin, previousOrigin; Motion projectedVelocity, updateAcceleration, updateVelocity; Time nextUpdate; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Collision support // public: virtual void MoveCollisionVolume(); BoundingBoxTreeNode* GetMoverCollisionRoot() {Check(this); return containedByNode;} BoxedSolidCollisionList* AllocateCollisionList(); BoxedSolidCollisionList* GetCurrentCollisions(BoxedSolidCollisionList *list=NULL); BoxedSolid* FindBoxedSolidHitBy( Line *line, Entity *except_by ); BoxedSolidCollisionList* CollideCenterOfMotion( Line *line, BoxedSolidCollisionList *list ); void ProcessCollisionList( BoxedSolidCollisionList *collisions, Scalar time_slice, const Point3D &old_position, Damage *damage ); Scalar StaticBounce( const Point3D &old_position, Scalar delta_t, Scalar penetration, const Normal &normal, Scalar *elasticity, Scalar bounce_min, Scalar *friction ); Scalar DynamicBounce( Mover *other, Scalar delta_t, Scalar penetration, const Normal &normal, Scalar *elasticity ); BoxedSolid* GetCollisionVolume() {Check(this); return collisionVolume;} BoxedSolid* GetCollisionTemplate() {Check(this); return collisionTemplate;} int GetCollisionVolumeCount() {Check(this); return collisionVolumeCount;} virtual void StartCollisionAssistant(); protected: int collisionVolumeCount; BoxedSolid *collisionVolume, *collisionTemplate; BoundingBoxTreeNode *containedByNode; BoxedSolidCollisionList *collisionLists, *lastCollisionList; CollisionAssistant *collisionAssistant; virtual void ProcessCollision( Scalar time_slice, BoxedSolidCollision &collision, const Point3D &old_position, Damage *damage ); void CheckAgainstBoxedSolidChain( BoxedSolidCollisionList *collisions, BoxedSolid *chain ); public: void CheckVolumeAgainstBoxedSolidChain( BoxedSolidCollisionList *collisions, BoxedSolid *chain ); protected: BoxedSolid* CheckLineAgainstBoxedSolidChain( Line *line, BoxedSolid *chain ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Flag Support // public: enum { NoCollisionVolumeBit = Entity::NextBit, NoCollisionTestBit, InitialStasisBit, NextBit }; enum { NoCollisionVolumeFlag = 1<