Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

contactjointhandler.cpp

Go to the documentation of this file.
00001 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*-
00002 
00003    this file is part of rcssserver3D
00004    Fri May 9 2003
00005    Copyright (C) 2002,2003 Koblenz University
00006    Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group
00007    $Id: contactjointhandler.cpp,v 1.8 2004/04/15 19:55:08 rollmark Exp $
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; version 2 of the License.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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     // set up default contact surface parameters
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             // undefined, default 0
00053             return 0.0f;
00054 
00055         case 1:
00056             // first one defined
00057             return v1;
00058 
00059         case 2:
00060             // second one defined
00061             return v2;
00062 
00063         case 3:
00064             // both defined, return average
00065             return (v1 + v2) / 2.0f;
00066         }
00067 }
00068 
00069 void
00070 ContactJointHandler::CalcSurfaceParam(dSurfaceParameters& surface,
00071                                       const dSurfaceParameters& collideeParam)
00072 {
00073     // init surface
00074     surface.mode = 0;
00075 
00076     // calculate average mu; mu can be dInfinity, so first multiply with
00077     // 0.5 and the sum up to avoid a range error
00078     surface.mu = mSurfaceParameter.mu*0.5f + collideeParam.mu*0.5f;
00079 
00080     // soft cfm
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     // soft_erp
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     // bounce
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     // to create a contact joint it we must have at least one body to
00134     // attach it to.
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     // check if the collidee has a ContactJointHandler registered to it
00147     shared_ptr<ContactJointHandler> handler =
00148         collidee->FindChildSupportingClass<ContactJointHandler>();
00149 
00150     if (handler.get() == 0)
00151         {
00152             return;
00153         }
00154 
00155     // calculate the resulting surface parameters
00156     CalcSurfaceParam(contact.surface,handler->mSurfaceParameter);
00157 
00158     // create the contact joint and attach it to the body
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 

Generated on Thu Apr 6 15:25:37 2006 for rcssserver3d by  doxygen 1.4.4