00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "contactjointhandler.h"
00023 #include "collider.h"
00024 #include "world.h"
00025 #include "space.h"
00026
00027 #include <zeitgeist/logserver/logserver.h>
00028
00029 using namespace oxygen;
00030 using namespace boost;
00031
00032 ContactJointHandler::ContactJointHandler() : CollisionHandler()
00033 {
00034
00035 mSurfaceParameter.mode = dContactBounce;
00036 mSurfaceParameter.mu = dInfinity;
00037 mSurfaceParameter.bounce = 0.8f;
00038 mSurfaceParameter.bounce_vel = 2.0f;
00039 }
00040
00041 ContactJointHandler::~ContactJointHandler()
00042 {
00043 }
00044
00045 float
00046 ContactJointHandler::MixValues(const float v1, const float v2, const int n) const
00047 {
00048 switch(n)
00049 {
00050 default:
00051 case 0:
00052
00053 return 0.0f;
00054
00055 case 1:
00056
00057 return v1;
00058
00059 case 2:
00060
00061 return v2;
00062
00063 case 3:
00064
00065 return (v1 + v2) / 2.0f;
00066 }
00067 }
00068
00069 void
00070 ContactJointHandler::CalcSurfaceParam(dSurfaceParameters& surface,
00071 const dSurfaceParameters& collideeParam)
00072 {
00073
00074 surface.mode = 0;
00075
00076
00077
00078 surface.mu = mSurfaceParameter.mu*0.5f + collideeParam.mu*0.5f;
00079
00080
00081 const int nCfm =
00082 ((mSurfaceParameter.mode & dContactSoftCFM) ? 1:0) +
00083 ((collideeParam.mode & dContactSoftCFM) ? 2:0);
00084
00085 if (nCfm>0)
00086 {
00087 surface.soft_cfm = MixValues
00088 (mSurfaceParameter.soft_cfm, collideeParam.soft_cfm, nCfm);
00089 surface.mode |= dContactSoftCFM;
00090 }
00091
00092
00093 const int nErp =
00094 ((mSurfaceParameter.mode & dContactSoftERP) ? 1:0) +
00095 ((collideeParam.mode & dContactSoftERP) ? 2:0);
00096
00097 if (nErp>0)
00098 {
00099 surface.soft_erp = MixValues
00100 (mSurfaceParameter.soft_erp, collideeParam.soft_erp, nErp);
00101 surface.mode |= dContactSoftERP;
00102 }
00103
00104
00105 const int nBounce =
00106 ((mSurfaceParameter.mode & dContactBounce) ? 1:0) +
00107 ((collideeParam.mode & dContactBounce) ? 2:0);
00108
00109 if (nBounce>0)
00110 {
00111 surface.bounce = MixValues
00112 (mSurfaceParameter.bounce, collideeParam.bounce, nBounce);
00113
00114 surface.bounce_vel = MixValues
00115 (mSurfaceParameter.bounce_vel, collideeParam.bounce_vel, nBounce);
00116
00117 surface.mode |= dContactBounce;
00118 }
00119 }
00120
00121 void
00122 ContactJointHandler::HandleCollision(shared_ptr<Collider> collidee, dContact& contact)
00123 {
00124 if (
00125 (mCollider.get() == 0) ||
00126 (mWorld.get() == 0) ||
00127 (mSpace.get() == 0)
00128 )
00129 {
00130 return;
00131 }
00132
00133
00134
00135 dBodyID myBody = dGeomGetBody(mCollider->GetODEGeom());
00136 dBodyID collideeBody = dGeomGetBody(collidee->GetODEGeom());
00137
00138 if (
00139 (myBody == 0) &&
00140 (collideeBody == 0)
00141 )
00142 {
00143 return;
00144 }
00145
00146
00147 shared_ptr<ContactJointHandler> handler =
00148 collidee->FindChildSupportingClass<ContactJointHandler>();
00149
00150 if (handler.get() == 0)
00151 {
00152 return;
00153 }
00154
00155
00156 CalcSurfaceParam(contact.surface,handler->mSurfaceParameter);
00157
00158
00159 dJointID joint = dJointCreateContact
00160 (mWorld->GetODEWorld(), mSpace->GetODEJointGroup(), &contact);
00161
00162 dJointAttach (joint, myBody, collideeBody);
00163 }
00164
00165 void
00166 ContactJointHandler::SetSurfaceParameter(const dSurfaceParameters& surface)
00167 {
00168 mSurfaceParameter = surface;
00169 }
00170
00171 void
00172 ContactJointHandler::SetContactMode(int mode, bool set)
00173 {
00174 if (set)
00175 {
00176 mSurfaceParameter.mode |= mode;
00177 } else
00178 {
00179 mSurfaceParameter.mode &= ~mode;
00180 }
00181 }
00182
00183 void
00184 ContactJointHandler::SetContactBounceMode(bool set)
00185 {
00186 SetContactMode(dContactBounce,set);
00187 }
00188
00189 void
00190 ContactJointHandler::SetMinBounceVel(float vel)
00191 {
00192 mSurfaceParameter.bounce_vel = std::max<float>(0.0f,vel);
00193 }
00194
00195 void
00196 ContactJointHandler::SetBounceValue(float bounce)
00197 {
00198 mSurfaceParameter.bounce = std::max<float>(0.0f,bounce);
00199 }
00200
00201 void
00202 ContactJointHandler::SetContactSoftERPMode(bool set)
00203 {
00204 SetContactMode(dContactSoftERP,set);
00205 }
00206
00207 void
00208 ContactJointHandler::SetContactSoftERP(float erp)
00209 {
00210 salt::gClamp(erp,0.0f,1.0f);
00211 mSurfaceParameter.soft_erp = erp;
00212 }
00213
00214 void
00215 ContactJointHandler::SetContactSoftCFMMode(bool set)
00216 {
00217 SetContactMode(dContactSoftCFM,set);
00218 }
00219
00220 void
00221 ContactJointHandler::SetContactSoftCFM(float cfm)
00222 {
00223 mSurfaceParameter.soft_cfm = std::max<float>(0.0f,cfm);
00224 }
00225
00226 void ContactJointHandler::SetContactSlipMode (bool set)
00227 {
00228 SetContactMode(dContactSlip1,set);
00229 SetContactMode(dContactSlip2,set);
00230 }
00231
00232 void ContactJointHandler::SetContactSlip(float slip)
00233 {
00234 mSurfaceParameter.slip1 = slip;
00235 mSurfaceParameter.slip2 = slip;
00236 }
00237
00238 void ContactJointHandler::SetContactMu(float mu)
00239 {
00240 mSurfaceParameter.mu = mu;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251