00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef SOFA_COMPONENT_COLLISION_RAYPICKINTERACTOR_H
00026 #define SOFA_COMPONENT_COLLISION_RAYPICKINTERACTOR_H
00027
00028 #include <sofa/component/collision/RayModel.h>
00029 #include <sofa/core/BehaviorModel.h>
00030
00031 #include <sofa/component/MechanicalObject.h>
00032 #include <sofa/simulation/tree/GNode.h>
00033 #include <sofa/component/collision/BarycentricContactMapper.h>
00034
00035
00036 #include <sofa/defaulttype/Vec.h>
00037 #include <sofa/defaulttype/Mat.h>
00038 #include <sofa/defaulttype/Quat.h>
00039 #include <sofa/core/componentmodel/collision/DetectionOutput.h>
00040
00041 #include <sofa/component/collision/TopologicalChangeManager.h>
00042
00043 #include <sofa/helper/Factory.h>
00044
00045 namespace sofa
00046 {
00047 namespace component
00048 {
00049 namespace collision
00050 {
00051 using namespace sofa::defaulttype;
00052
00053 class BasePickingManager : public virtual sofa::core::objectmodel::BaseObject
00054 {
00055 public:
00056 virtual ~BasePickingManager();
00057 virtual bool attach(int button, core::CollisionElementIterator elem1, core::CollisionElementIterator elem2, double dist, Vector3 p1, Vector3 p2) = 0;
00058 virtual bool isAttached() = 0;
00059 virtual void release() = 0;
00060 virtual void update() = 0;
00061
00062 typedef helper::Factory<std::string, BasePickingManager, core::objectmodel::BaseContext*> PickingManagerFactory;
00063
00064 static BasePickingManager* Create(std::string name, core::objectmodel::BaseContext* context);
00065 static int CreateAll(std::vector<BasePickingManager*>& instances, core::objectmodel::BaseContext* context);
00066
00067 template <class RealObject>
00068 static bool canCreate( RealObject*& , core::objectmodel::BaseContext* )
00069 {
00070 return true;
00071 }
00072
00073 template <class RealObject>
00074 static void create( RealObject*& obj, core::objectmodel::BaseContext* context)
00075 {
00076 if (RealObject::canCreate(obj, context))
00077 {
00078 obj = new RealObject;
00079
00080
00081 }
00082 }
00083 };
00084
00085 class RayPickInteractor : public RayModel, public core::BehaviorModel
00086 {
00087 public:
00088 RayPickInteractor();
00089 ~RayPickInteractor();
00090
00091 virtual void init();
00092
00093 virtual bool isActive();
00094
00096 virtual void updatePosition(double dt);
00097
00099 virtual void newPosition(const Vector3& translation, const Quat& rotation, const Mat4x4d& transformation);
00100 virtual void newEvent(const std::string& command);
00101
00102 virtual void draw();
00103
00104 virtual bool isAttached();
00105
00106
00107 protected:
00108 void pickBody();
00109 void releaseBody();
00110
00111 core::componentmodel::collision::DetectionOutput* findFirstCollision(const Ray& ray, double* dist);
00112
00113
00114 enum { DISABLED, PRESENT, ACTIVE, ATTACHED, FIRST_INPUT, SECOND_INPUT, IS_CUT } state;
00115 int button;
00116 Mat4x4d transform;
00117
00118 helper::vector<BasePickingManager*> pickManagers;
00119
00120
00121 TopologicalChangeManager topo_changeManager;
00122
00123 };
00124
00125
00126 template<class TDataTypes, class ContactForceField>
00127 class DefaultPickingManager : public BasePickingManager
00128 {
00129 public:
00130 typedef TDataTypes DataTypes;
00131 typedef typename DataTypes::Real Real;
00132 typedef typename DataTypes::Coord Coord;
00133
00134 Data<int> button;
00135
00136 DefaultPickingManager();
00137
00138 virtual bool attach(int button, core::CollisionElementIterator elem1, core::CollisionElementIterator elem2, double dist, Vector3 p1, Vector3 p2)
00139 {
00140 if (button == this->button.getValue())
00141 return attach(elem1, elem2, dist, p1, p2);
00142 return false;
00143 }
00144 virtual bool isAttached()
00145 {
00146 return !attachedPoints.empty();
00147 }
00148 virtual void release();
00149 virtual void update();
00150 virtual void draw();
00151
00152 template <class RealObject>
00153 static bool canCreate( RealObject*& obj, core::objectmodel::BaseContext* context)
00154 {
00155 if (context != NULL)
00156 {
00157 core::componentmodel::behavior::MechanicalState<DataTypes>* p = NULL;
00158 context->get(p, core::objectmodel::BaseContext::SearchRoot);
00159 if (p == NULL)
00160 return false;
00161 }
00162 return BasePickingManager::canCreate(obj, context);
00163 }
00164
00165 protected:
00166
00167 virtual component::MechanicalObject<DataTypes>* getMState(core::objectmodel::BaseContext* context);
00168
00169 virtual bool attach(core::CollisionElementIterator elem1, core::CollisionElementIterator elem2, double dist, Vector3 p1, Vector3 p2);
00170
00171 virtual void addContact(ContactForceField* ff, int index1, int index2, double stiffness, double mu_v, double length, const Vector3& p1, const Vector3& p2);
00172
00173 sofa::helper::vector< std::pair<Ray,double> > attachedPoints;
00174 component::MechanicalObject<DataTypes>* mechanicalObject;
00175 sofa::helper::vector<core::componentmodel::behavior::BaseForceField*> forcefields;
00176 sofa::helper::vector<BaseContactMapper<DataTypes>*> mappers;
00177 };
00178
00179 }
00180
00181 }
00182
00183 }
00184
00185 #endif