00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "collider.h"
00022 #include "space.h"
00023 #include "body.h"
00024 #include "collisionhandler.h"
00025 #include <oxygen/sceneserver/scene.h>
00026 #include <zeitgeist/logserver/logserver.h>
00027
00028 using namespace oxygen;
00029 using namespace salt;
00030 using namespace boost;
00031 using namespace std;
00032
00033 Collider::Collider() : ODEObject(), mODEGeom(0)
00034 {
00035 }
00036
00037 Collider::~Collider()
00038 {
00039 if (mODEGeom)
00040 {
00041 dGeomDestroy(mODEGeom);
00042 mODEGeom = 0;
00043 }
00044 }
00045
00046 void Collider::OnLink()
00047 {
00048 ODEObject::OnLink();
00049
00050 if (mODEGeom == 0)
00051 {
00052 return;
00053 }
00054
00055
00056 dSpaceID space = GetSpaceID();
00057 if (
00058 (space) &&
00059 (! dSpaceQuery(space, mODEGeom))
00060 )
00061 {
00062 dGeomSetData(mODEGeom, this);
00063 dSpaceAdd(space, mODEGeom);
00064 }
00065
00066
00067 shared_ptr<Body> body = shared_static_cast<Body>
00068 (make_shared(GetParent())->GetChildOfClass("Body"));
00069
00070 if (body.get() != 0)
00071 {
00072 dGeomSetBody (mODEGeom, body->GetODEBody());
00073 } else
00074 {
00075
00076
00077 SetRotation(GetWorldTransform());
00078 SetPosition(Vector3f(0,0,0));
00079 }
00080 }
00081
00082 void Collider::OnUnlink()
00083 {
00084 ODEObject::OnUnlink();
00085
00086
00087 dSpaceID space = GetSpaceID();
00088
00089 if (
00090 (mODEGeom == 0) ||
00091 (space == 0)
00092 )
00093 {
00094 return;
00095 }
00096
00097 if (
00098 (space) &&
00099 (dSpaceQuery(space, mODEGeom))
00100 )
00101 {
00102 dSpaceRemove(space, mODEGeom);
00103 }
00104 }
00105
00106 void Collider::PrePhysicsUpdateInternal(float )
00107 {
00108 if (GetChildSupportingClass("CollisionHandler").get() == 0)
00109 {
00110
00111
00112
00113
00114 AddCollisionHandler("oxygen/ContactJointHandler");
00115 }
00116 }
00117
00118 dGeomID Collider::GetODEGeom()
00119 {
00120 return mODEGeom;
00121 }
00122
00123 bool Collider::AddCollisionHandler(const std::string& handlerName)
00124 {
00125 GetCore()->New(handlerName);
00126
00127 shared_ptr<CollisionHandler> handler =
00128 shared_dynamic_cast<CollisionHandler>(GetCore()->New(handlerName));
00129
00130 if (handler.get() == 0)
00131 {
00132 GetLog()->Error()
00133 << "ERROR: (Collider) Cannot create CollisionHandler "
00134 << handlerName << "\n";
00135 return false;
00136 }
00137
00138 return AddChildReference(handler);
00139 }
00140
00141 void Collider::OnCollision (boost::shared_ptr<Collider> collidee,
00142 dContact& contact, ECollisionType type)
00143
00144 {
00145 TLeafList handlers;
00146 ListChildrenSupportingClass<CollisionHandler>(handlers);
00147
00148 for (
00149 TLeafList::iterator iter = handlers.begin();
00150 iter != handlers.end();
00151 ++iter
00152 )
00153 {
00154 shared_ptr<CollisionHandler> handler =
00155 shared_static_cast<CollisionHandler>(*iter);
00156
00157 if (
00158 (type == CT_SYMMETRIC) &&
00159 (! handler->IsSymmetricHandler())
00160 )
00161 {
00162 continue;
00163 }
00164
00165 handler->HandleCollision(collidee, contact);
00166 }
00167 }
00168
00169 shared_ptr<Collider> Collider::GetCollider(dGeomID id)
00170 {
00171 if (id == 0)
00172 {
00173 return shared_ptr<Collider>();
00174 }
00175
00176 Collider* collPtr =
00177 static_cast<Collider*>(dGeomGetData(id));
00178
00179 if (collPtr == 0)
00180 {
00181
00182 cerr << "ERROR: (Collider) no Collider found for dGeomID "
00183 << id << "\n";
00184 return shared_ptr<Collider>();
00185 }
00186
00187 shared_ptr<Collider> collider = shared_static_cast<Collider>
00188 (make_shared(collPtr->GetSelf()));
00189
00190 if (collider.get() == 0)
00191 {
00192
00193 cerr << "ERROR: (Collider) got no shared_ptr for dGeomID "
00194 << id << "\n";
00195 }
00196
00197 return collider;
00198 }
00199
00200 void Collider::SetRotation(const Matrix& rot)
00201 {
00202 dMatrix3 m;
00203 ConvertRotationMatrix(rot,m);
00204 dGeomSetRotation(mODEGeom,m);
00205 }
00206
00207 void Collider::SetPosition(const Vector3f& pos)
00208 {
00209 Vector3f globalPos(GetWorldTransform() * pos);
00210 dGeomSetPosition (mODEGeom, globalPos[0], globalPos[1], globalPos[2]);
00211 }
00212
00213 bool Collider::Intersects(boost::shared_ptr<Collider> collider)
00214 {
00215 if (
00216 (mODEGeom == 0) ||
00217 (collider.get() == 0)
00218 )
00219 {
00220 return false;
00221 }
00222
00223 dContactGeom contact;
00224
00225 return dCollide
00226 (
00227 mODEGeom,
00228 collider->GetODEGeom(),
00229 1,
00230 &contact,
00231 sizeof(contact)
00232 ) > 0;
00233 }
00234