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 #include <physics/ODEContactConstraint>
00026 #include <physics/ODEConstraintGroup>
00027 #include <physics/ODESolid>
00028
00029 using physics::ODEContactConstraint;
00030 using physics::ContactConstraint;
00031 using physics::Body;
00032 using physics::ODESolid;
00033
00034
00035 ODEContactConstraint::ODEContactConstraint()
00036 : addedToGroup(false)
00037 {
00038 }
00039
00040 ODEContactConstraint::~ODEContactConstraint()
00041 {
00042 }
00043
00044
00045 void ODEContactConstraint::attach(ref<Body> body1, ref<Body> body2)
00046 {
00047 Assert(body1 != 0);
00048 Assert(body2 != 0);
00049 Assertm(body1 != body2, "body1 is not body2");
00050
00051 if (!addedToGroup)
00052 throw std::runtime_error(Exception("Constraint must be added to a ConstraintGroup before being attached to bodies"));
00053
00054 ref<ODEConstraintGroup> ogroup = narrow_ref<ODEConstraintGroup>(group);
00055 Assert(ogroup->getWorldID());
00056
00057 this->body1 = body1;
00058 this->body2 = body2;
00059
00060
00061 base::clearMemory(&oc,1);
00062 oc.surface.mode = dContactApprox1 | dContactSoftERP | dContactSoftCFM | dContactBounce;
00063
00064
00065 oc.surface.mu = 8;
00066
00067
00068 oc.surface.soft_erp = 0.5;
00069 oc.surface.soft_cfm = 1e-5;
00070 oc.surface.bounce = 0.3;
00071
00072
00073
00074 Point3 gpos(body1->getOrientation().rotate(position) + body1->getPosition() );
00075 oc.geom.pos[0] = gpos.x;
00076 oc.geom.pos[1] = gpos.y;
00077 oc.geom.pos[2] = gpos.z;
00078
00079 Vector3 gnormal(body1->getOrientation().rotate(normal));
00080 oc.geom.normal[0] = gnormal.x;
00081 oc.geom.normal[1] = gnormal.y;
00082 oc.geom.normal[2] = gnormal.z;
00083
00084
00085 oc.geom.depth = depth;
00086
00087 dJointID cj = dJointCreateContact(ogroup->getWorldID(), ogroup->getJointGroupID(), &oc);
00088
00089 setJointID(cj);
00090
00091 ref<ODESolid> solid1 = narrow_ref<ODESolid>(body1);
00092 ref<ODESolid> solid2 = narrow_ref<ODESolid>(body2);
00093
00094 dJointAttach(jointID, solid1->getBodyID(), solid2->getBodyID());
00095
00096 }
00097
00098
00099 ref<Body> ODEContactConstraint::getBody(Int index)
00100 {
00101 Assert(index < 2);
00102 return (index==0)?body1:body2;
00103 }
00104
00105 ref<const Body> ODEContactConstraint::getBody(Int index) const
00106 {
00107 Assert(index < 2);
00108 return (index==0)?body1:body2;
00109 }
00110
00111
00112 void ODEContactConstraint::onConstraintGroupAdd(ref<ConstraintGroup> g)
00113 {
00114 Assert(g != 0);
00115 Assert(instanceof(*g,ODEConstraintGroup));
00116 group = g;
00117
00118 if (Math::equals(normal.norm(),0) && Math::equals(position.norm(),0))
00119 throw std::runtime_error(Exception("must set ContactConstraint position,normal & depth before adding it to a ConstraintGroup"));
00120
00121 addedToGroup = true;
00122
00123
00124 }
00125
00126
00127 void ODEContactConstraint::setContactPosition(const Point3& pos)
00128 {
00129 Assertm(group==0, "contact position set before ContactConstraint added to ConstraintGroup");
00130 position = pos;
00131 }
00132
00133
00134 void ODEContactConstraint::setContactNormal(const Vector3& normal)
00135 {
00136 Assertm(group==0, "contact normal set before ContactConstraint added to ConstraintGroup");
00137 this->normal = normal;
00138 }
00139
00140
00141 void ODEContactConstraint::setContactDepth(Real depth)
00142 {
00143 Assertm(group==0, "contact depth set before ContactConstraint added to ConstraintGroup");
00144 this->depth = depth;
00145 }
00146
00147