00001 #ifdef HAVE_BULLET
00002
00003 #include "PhysicsBody.h"
00004 #include "PhysicsWorld.h"
00005 #include "MotorControllers.h"
00006 #include "Shared/ReferenceCounter.h"
00007 #include "Shared/debuget.h"
00008
00009 #ifdef HAVE_OGRE
00010 # ifdef __APPLE__
00011 # include <Ogre/OgreMesh.h>
00012 # include <Ogre/OgreSubMesh.h>
00013 # else
00014 # include <OGRE/OgreMesh.h>
00015 # include <OGRE/OgreSubMesh.h>
00016 # endif
00017 #endif
00018
00019 #ifdef __APPLE__
00020 #include <BulletCollision/btBulletCollisionCommon.h>
00021 #include <BulletDynamics/btBulletDynamicsCommon.h>
00022 #else
00023 #include <btBulletCollisionCommon.h>
00024 #include <btBulletDynamicsCommon.h>
00025 #endif
00026
00027 #include <stdexcept>
00028
00029 using namespace std;
00030
00031 std::ostream& operator<<(std::ostream& os, const btTransform& t) {
00032 fmat::Matrix<4,4> ft;
00033 for(unsigned int i=0; i<3; ++i)
00034 for(unsigned int j=0; j<3; ++j)
00035 ft(i,j) = t.getBasis()[i][j];
00036 (fmat::SubVector<3>)ft.column(3) = t.getOrigin();
00037 ft(3,3)=1;
00038 return os << ft;
00039 }
00040
00041 std::ostream& operator<<(std::ostream& os, const btVector3& v) {
00042 return os << fmat::SubVector<3>(const_cast<float*>(&v[0]));
00043 }
00044
00045
00046 struct CollisionData : public ReferenceCounter {
00047 #ifdef HAVE_OGRE
00048 CollisionData(const std::string& meshName, Ogre::MeshPtr mesh);
00049 #endif
00050 ~CollisionData() {
00051 delete vertices; vertices=NULL;
00052 delete indices; indices=NULL;
00053 PhysicsBody::collisionData.erase(name);
00054 }
00055 std::string name;
00056 float * vertices;
00057 unsigned int * indices;
00058 };
00059
00060 std::map<std::string,CollisionData*> PhysicsBody::collisionData;
00061
00062
00063 PhysicsBody::~PhysicsBody() {
00064
00065
00066 if(parentBody!=NULL)
00067 parentBody->children.erase(this);
00068
00069 for(std::set<PhysicsBody*>::const_iterator it=children.begin(); it!=children.end(); ++it) {
00070 (*it)->parentBody = parentBody;
00071 if(parentBody!=NULL)
00072 parentBody->children.insert(*it);
00073 }
00074 ASSERT(children.size()==0 || parentBody!=NULL, "deleting PhysicsBody with children but no parent");
00075 children.clear();
00076 clear();
00077 parentBody=NULL;
00078 std::map<LinkComponent*, PhysicsBody*>::iterator it = world.bodies.find(&link);
00079 if(it==world.bodies.end()) {
00080 std::cerr << "WARNING PhysicsBody: body was not found in world for removal" << std::endl;
00081 } else {
00082 world.bodies.erase(it);
00083 }
00084 }
00085
00086 std::string PhysicsBody::getPath() const {
00087 stringstream ss;
00088 if(const KinematicJoint* kj = dynamic_cast<const KinematicJoint*>(&link)) {
00089 ss << kj->getPath() << ":" << getModel();
00090 } else {
00091 ss << "Free-" << getModel();
00092 }
00093 ss << "@" << &link;
00094 return ss.str();
00095 }
00096
00097 void PhysicsBody::getCurrent(fmat::Column<3>& pos, fmat::Quaternion& quat) const {
00098 ASSERTRET(body!=NULL,"PhysicsData::getCurrent called with NULL body");
00099
00100 const btTransform& t = body->getWorldTransform();
00101
00102 pos.importFrom(t * -centerOffset / world.spaceScale);
00103
00104 btQuaternion q = t.getRotation();
00105 quat = fmat::Quaternion(q.w(),q.x(),q.y(),q.z());
00106 }
00107
00108 bool PhysicsBody::hasJoint() const { return jointInterface!=NULL; }
00109
00110 float PhysicsBody::getJoint() const { return jointInterface->getValue(0); }
00111
00112 void PhysicsBody::teleport(const fmat::Column<3>& pos) {
00113 btTransform cur = body->getWorldTransform();
00114 float sc = world.spaceScale;
00115 cur.setOrigin(btVector3(pos[0]*sc,pos[1]*sc,pos[2]*sc));
00116 teleport(cur);
00117 }
00118
00119 void PhysicsBody::teleport(const fmat::Quaternion& quat) {
00120 btTransform cur = body->getWorldTransform();
00121 cur.setOrigin(cur.getOrigin() - quatRotate(cur.getRotation(),centerOffset));
00122 cur.setRotation(btQuaternion(quat.getX(),quat.getY(),quat.getZ(),quat.getW()));
00123 teleport(cur);
00124 }
00125
00126 void PhysicsBody::teleport(const fmat::Column<3>& pos, const fmat::Quaternion& quat) {
00127 float sc = world.spaceScale;
00128 btTransform cur(btQuaternion(quat.getX(),quat.getY(),quat.getZ(),quat.getW()),btVector3(pos[0]*sc,pos[1]*sc,pos[2]*sc));
00129 teleport(cur);
00130 }
00131
00132 void PhysicsBody::teleport(const btTransform& tr) {
00133 std::vector<std::pair<PhysicsBody*,btTransform> > cts;
00134
00135 for(std::set<PhysicsBody*>::const_iterator it=children.begin(); it!=children.end(); ++it) {
00136 btTransform cur = (*it)->body->getWorldTransform();
00137 cur.setOrigin(cur.getOrigin() - quatRotate(cur.getRotation(),(*it)->centerOffset));
00138 cts.push_back(std::make_pair(*it,cur));
00139 }
00140 clear();
00141 lastTransform = tr;
00142 build();
00143 for(std::vector<std::pair<PhysicsBody*,btTransform> >::const_iterator it=cts.begin(); it!=cts.end(); ++it)
00144 it->first->teleport(it->second);
00145 }
00146
00147 void PhysicsBody::setVelocity(const fmat::Column<3>& linear, const fmat::Column<3>& angular) {
00148 float sc = world.spaceScale;
00149 setVelocity(btVector3(linear[0]*sc,linear[1]*sc,linear[2]*sc), btVector3(angular[0],angular[1],angular[2]));
00150 }
00151 void PhysicsBody::setVelocity(const btVector3& linear, const btVector3& angular) {
00152 assert(!isnan(linear[0]));
00153 assert(!isnan(angular[0]));
00154
00155 const btTransform& t = body->getWorldTransform();
00156
00157 body->activate();
00158 body->setLinearVelocity(linear + angular.cross(t.getBasis() * centerOffset));
00159 body->setAngularVelocity(angular);
00160 for(std::set<PhysicsBody*>::const_iterator it=children.begin(); it!=children.end(); ++it) {
00161
00162
00163 (*it)->setVelocity(linear,angular);
00164 }
00165 }
00166
00167 void PhysicsBody::init() {
00168
00169 if(parentBody!=NULL) {
00170
00171 for(std::set<PhysicsBody*>::const_iterator it=parentBody->children.begin(); it!=parentBody->children.end(); ++it) {
00172 if(isChild(link,(*it)->link)) {
00173 children.insert(*it);
00174 }
00175 }
00176
00177 for(std::set<PhysicsBody*>::const_iterator it=children.begin(); it!=children.end(); ++it) {
00178 (*it)->parentBody=this;
00179 parentBody->children.erase(*it);
00180 }
00181
00182 parentBody->children.insert(this);
00183 }
00184 ASSERTIF(world.bodies.find(&link)==world.bodies.end(),"WARNING PhysicsBody: body already added to world!") {
00185 world.bodies[&link] = this;
00186 }
00187 build();
00188 }
00189
00190 void PhysicsBody::build() {
00191
00192 if(body==NULL) {
00193 ASSERT(compound==NULL,"have compound for collision shape but no body?");
00194 compound = new btCompoundShape;
00195
00196 } else {
00197 ASSERT(compound!=NULL,"have body but no compound for collision shape?");
00198 }
00199
00200 fmat::Column<3> com;
00201 link.sumLinkCenterOfMass(com,totalMass);
00202 (com * world.spaceScale).exportTo(centerOffset);
00203 totalMass*=world.massScale;
00204
00205 inertia.setValue(0,0,0);
00206
00207
00208 buildLink(link, fmat::Transform::identity());
00209
00210
00211
00212
00213
00214 btVector3 localInertia;
00215 compound->calculateLocalInertia(totalMass,localInertia);
00216 inertia+=localInertia;
00217
00218
00219
00220
00221 ASSERT(totalMass==0 || compound->getNumChildShapes()>0,"PhysicsBody created with mass but no collision shape")
00222
00223 if(body!=NULL) {
00224
00225
00226
00227
00228
00229
00230 world.dynamicsWorld->removeRigidBody(body);
00231 resetTransform();
00232 world.dynamicsWorld->addRigidBody(body);
00233
00234 } else {
00235
00236
00237
00238 btRigidBody::btRigidBodyConstructionInfo rbInfo(totalMass,NULL,compound,inertia);
00239
00240
00241
00242
00243
00244
00245 body = new btRigidBody(rbInfo);
00246 body->setDamping(world.linearDamping, world.angularDamping);
00247 body->setUserPointer(this);
00248
00249
00250 resetTransform();
00251 world.dynamicsWorld->addRigidBody(body);
00252 }
00253
00254
00255 if(parentBody==NULL) {
00256
00257 } else {
00258 btTransform pT;
00259 const fmat::Transform fm = link.getT(parentBody->link);
00260 pT.setBasis(btMatrix3x3(fm(0,0),fm(0,1),fm(0,2), fm(1,0),fm(1,1),fm(1,2), fm(2,0),fm(2,1),fm(2,2)));
00261 pT.setOrigin(btVector3(fm(0,3),fm(1,3),fm(2,3)) * world.spaceScale - parentBody->centerOffset);
00262
00263 btTransform lT;
00264 lT.setBasis(btMatrix3x3::getIdentity());
00265 lT.setOrigin(-centerOffset);
00266 if(qpos!=NULL) {
00267 btMatrix3x3& rot = lT.getBasis();
00268 rot[0][0] = rot[1][1] = std::cos(*qpos);
00269 rot[0][1] = -(rot[1][0] = std::sin(*qpos));
00270 }
00271
00272
00273
00274 ASSERT(joint==NULL,"PhysicsBody already has joint!?");
00275 joint = new btGeneric6DofConstraint(*parentBody->body,*body,pT,lT,true);
00276
00277
00278 const float ERP=0.f, SOFT=0.0f;
00279 joint->getTranslationalLimitMotor()->m_restitution=0;
00280 joint->getTranslationalLimitMotor()->m_limitSoftness=SOFT;
00281 for(unsigned int i=0; i<3; ++i) {
00282 joint->getRotationalLimitMotor(i)->m_limitSoftness=SOFT;
00283 #if BT_BULLET_VERSION<276
00284 joint->getRotationalLimitMotor(i)->m_ERP=ERP;
00285 #else
00286 joint->getTranslationalLimitMotor()->m_stopERP[i] = ERP;
00287 joint->getTranslationalLimitMotor()->m_stopCFM[i] = SOFT;
00288 joint->getTranslationalLimitMotor()->m_normalCFM[i] = SOFT;
00289 joint->getRotationalLimitMotor(i)->m_stopERP = ERP;
00290 joint->getRotationalLimitMotor(i)->m_stopCFM = SOFT;
00291 joint->getRotationalLimitMotor(i)->m_normalCFM = SOFT;
00292 #endif
00293 }
00294 if(qpos==NULL) {
00295
00296
00297
00298 joint->setAngularLowerLimit(btVector3(0,0,0));
00299 joint->setAngularUpperLimit(btVector3(0,0,0));
00300 } else if(link.controllerInfo.velocity) {
00301
00302 joint->setAngularLowerLimit(btVector3(0,0,1));
00303 joint->setAngularUpperLimit(btVector3(0,0,-1));
00304 jointInterface = new GenericAngularMotorInterface(*joint);
00305 float scale=1;
00306 const fmat::Column<3> aabbdim = link.getAABB().getDimensions();
00307 if(aabbdim[0]!=aabbdim[1])
00308 std::cerr << "non-symmetric wheel boundaries? what's the radius?" << std::endl;
00309 if(aabbdim[0]<=0) {
00310 std::cerr << "wheel diameter is non-positive" << std::endl;
00311 } else {
00312 scale = 2/aabbdim[0];
00313 }
00314 jointController = new LinearMotorController(*qpos,*jointInterface,scale);
00315 } else {
00316
00317 joint->setAngularLowerLimit(btVector3(0,0,-link.qmax));
00318 joint->setAngularUpperLimit(btVector3(0,0,-link.qmin));
00319 for(unsigned int i=0; i<3; ++i) {
00320 joint->getRotationalLimitMotor(i)->m_maxMotorForce=8000;
00321 joint->getRotationalLimitMotor(i)->m_maxLimitForce=8000;
00322 }
00323 if(link.controllerInfo.forceControl) {
00324 jointInterface = new GenericAngularMotorInterface(*joint);
00325 PIDMotorController * tmp = new PIDMotorController(*qpos,*jointInterface);
00326 tmp->p = 10;
00327 tmp->i = 0;
00328 tmp->d = 0;
00329 jointController = tmp;
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 } else {
00341 jointInterface = new GenericAngularPositionInterface(*joint);
00342 jointController = new LinearMotorController(*qpos,*jointInterface);
00343 }
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 if(jointController!=NULL) {
00380 jointController->set(link.controllerInfo);
00381 world.motorControllers.insert(jointController);
00382 }
00383 if(joint!=NULL)
00384 world.dynamicsWorld->addConstraint(joint, true);
00385
00386
00387
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 updateFrictionForce();
00400 updateAnistropicFriction();
00401 }
00402
00403 void PhysicsBody::buildLink(const KinematicJoint& kj, const fmat::Transform& tr) {
00404 addComponent(kj,tr);
00405 for(KinematicJoint::component_iterator it=kj.components.begin(); it!=kj.components.end(); ++it) {
00406 addComponent(**it,tr);
00407 }
00408 for(KinematicJoint::branch_iterator it=kj.getBranches().begin(); it!=kj.getBranches().end(); ++it) {
00409 if(!(*it)->hasMass()) {
00410 buildLink(**it,tr * (*it)->getTq());
00411 }
00412 }
00413 }
00414
00415 void PhysicsBody::addComponent(const LinkComponent& comp, const fmat::Transform& tr) {
00416 if(comp.collisionModel.size()==0) {
00417 if(comp.mass>0) {
00418
00419 float m = comp.mass * world.massScale;
00420 fmat::Column<3> com;
00421 com.importFrom(comp.centerOfMass);
00422 com = tr * com * world.spaceScale;
00423 btVector3 localInertia = btVector3(com[0],com[1],com[2]) - centerOffset;
00424 inertia += btVector3(localInertia[0]*localInertia[0]*m, localInertia[1]*localInertia[1]*m, localInertia[2]*localInertia[2]*m);
00425 }
00426 return;
00427 }
00428
00429 const fmat::Column<3> dim = fmat::Column<3>().importFrom(comp.collisionModelScale);
00430 const fmat::Column<3> pos = fmat::Column<3>().importFrom(comp.collisionModelOffset);
00431 fmat::Quaternion rot = fmat::Quaternion::fromAxis(comp.collisionModelRotation);
00432 btVector3 dim_2, origin;
00433 (dim/2 * world.spaceScale).exportTo(dim_2);
00434 (tr * pos * world.spaceScale).exportTo(origin);
00435 rot = fmat::Quaternion::fromMatrix(tr.rotation()) * rot;
00436 if(comp.collisionModel=="Cube") {
00437 btCollisionShape * collide = new btBoxShape(dim_2);
00438 collide->setMargin(world.collisionMargin*world.spaceScale);
00439 const btTransform btr(btQuaternion(rot.getX(),rot.getY(),rot.getZ(),rot.getW()), origin - centerOffset);
00440 compound->addChildShape(btr,collide);
00441
00442 } else if(comp.collisionModel=="Sphere") {
00443 btCollisionShape * collide=NULL;
00444 if(dim[0]==dim[1] && dim[0]==dim[2]) {
00445 collide = new btSphereShape(dim_2[0]);
00446 } else {
00447 btVector3 center(0,0,0);
00448 btScalar radi=1;
00449 collide = new btMultiSphereShape(¢er,&radi,1);
00450 collide->setLocalScaling(dim_2);
00451 }
00452 collide->setMargin(world.collisionMargin*world.spaceScale);
00453 const btTransform btr(btQuaternion(rot.getX(),rot.getY(),rot.getZ(),rot.getW()), origin - centerOffset);
00454 compound->addChildShape(btr,collide);
00455 } else if(comp.collisionModel=="Cylinder") {
00456 btCollisionShape * collide = new btCylinderShapeZ(dim_2);
00457 collide->setMargin(world.collisionMargin*world.spaceScale);
00458 const btTransform btr(btQuaternion(rot.getX(),rot.getY(),rot.getZ(),rot.getW()), origin - centerOffset);
00459 compound->addChildShape(btr,collide);
00460 } else if(comp.collisionModel=="Plane") {
00461 fmat::Column<3> normal = rot * fmat::UNIT3_Z;
00462 fmat::fmatReal dist = fmat::dotProduct(normal,pos) * world.spaceScale;
00463 btCollisionShape * collide = new btStaticPlaneShape(normal.exportTo<btVector3>(),dist);
00464
00465 compound->addChildShape(btTransform::getIdentity(),collide);
00466 } else {
00467 #ifdef HAVE_OGRE
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 #endif
00478 }
00479 }
00480
00481 void PhysicsBody::resetTransform() {
00482 btTransform pT_w;
00483 if(parentBody==NULL) {
00484 pT_w.setBasis(lastTransform.getBasis());
00485 pT_w.setOrigin(lastTransform.getOrigin());
00486 } else {
00487 pT_w = parentBody->body->getWorldTransform();
00488 const btVector3& parentOffset = parentBody->centerOffset;
00489 pT_w.setOrigin(pT_w * -parentOffset);
00490 }
00491
00492
00493 if(qpos!=NULL)
00494 link.tryQ(*qpos);
00495 btTransform kjT_p;
00496 if(parentBody==NULL) {
00497 if(KinematicJoint* kj = dynamic_cast<KinematicJoint*>(&link)) {
00498 const fmat::Transform fm = kj->getFullT();
00499 kjT_p.setBasis(btMatrix3x3(fm(0,0),fm(0,1),fm(0,2), fm(1,0),fm(1,1),fm(1,2), fm(2,0),fm(2,1),fm(2,2)));
00500 kjT_p.setOrigin(btVector3(fm(0,3),fm(1,3),fm(2,3)) * world.spaceScale);
00501 } else {
00502 kjT_p = btTransform::getIdentity();
00503 }
00504 } else {
00505 KinematicJoint& parentKJ = dynamic_cast<KinematicJoint&>(parentBody->link);
00506 const fmat::Transform fm = dynamic_cast<KinematicJoint&>(link).getT(parentKJ);
00507 kjT_p.setBasis(btMatrix3x3(fm(0,0),fm(0,1),fm(0,2), fm(1,0),fm(1,1),fm(1,2), fm(2,0),fm(2,1),fm(2,2)));
00508 kjT_p.setOrigin(btVector3(fm(0,3),fm(1,3),fm(2,3)) * world.spaceScale);
00509 }
00510
00511 const btTransform kjT_w = pT_w * kjT_p;
00512 const btVector3 b_w = kjT_w * centerOffset;
00513
00514 body->setWorldTransform(btTransform(kjT_w.getBasis(),b_w));
00515
00516
00517
00518
00519 }
00520
00521 void PhysicsBody::clear() {
00522
00523 if(body!=NULL) {
00524 ASSERT( (jointController==NULL && jointInterface==NULL) || (jointController!=NULL && jointInterface!=NULL), "Have some joint constraint objects, but not all?");
00525 if(jointController!=NULL) {
00526 world.motorControllers.erase(jointController);
00527 delete jointController; jointController=NULL;
00528 }
00529 if(jointInterface!=NULL) {
00530 delete jointInterface; jointInterface=NULL;
00531 }
00532 if(joint!=NULL) {
00533 world.dynamicsWorld->removeConstraint(joint);
00534 delete joint; joint=NULL;
00535 }
00536 lastTransform = body->getWorldTransform();
00537 lastTransform.setOrigin(lastTransform.getOrigin() - quatRotate(lastTransform.getRotation(),centerOffset));
00538
00539 for(int i=compound->getNumChildShapes()-1; i>=0; --i) {
00540 delete compound->getChildShape(i);
00541 compound->removeChildShapeByIndex(i);
00542 }
00543 if(collisionDataName.size()>0)
00544 collisionData[collisionDataName]->removeReference();
00545 collisionDataName.clear();
00546
00547 if(children.size()>0) {
00548
00549 } else {
00550 world.dynamicsWorld->removeRigidBody(body);
00551 delete body; body=NULL;
00552 delete compound; compound = NULL;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562 } else {
00563 ASSERT(jointController==NULL,"have jointController but no body?");
00564 ASSERT(jointInterface==NULL,"have jointInterface but no body?");
00565 ASSERT(joint==NULL,"have joint but no body?");
00566 ASSERT(compound->getNumChildShapes()==0,"have collision shape but no body?");
00567 ASSERT(collisionDataName.size()>0,"have collisionDataName but no body?");
00568 }
00569 }
00570
00571 void PhysicsBody::updateFrictionForce() {
00572 body->setFriction(link.frictionForce);
00573 }
00574
00575 void PhysicsBody::updateAnistropicFriction() {
00576 body->setAnisotropicFriction(btVector3(link.anistropicFrictionRatio[0],link.anistropicFrictionRatio[1],link.anistropicFrictionRatio[2]));
00577 }
00578
00579 bool PhysicsBody::isChild(const LinkComponent& pb, const LinkComponent& child) {
00580 if(const KinematicJoint* kj = dynamic_cast<const KinematicJoint*> (&pb)) {
00581 if(std::find(kj->components.begin(),kj->components.end(),&child) != kj->components.end())
00582 return true;
00583 for(KinematicJoint::branch_iterator it=kj->getBranches().begin(); it!=kj->getBranches().end(); ++it)
00584 if(isChild(**it,child))
00585 return true;
00586 }
00587 return false;
00588 }
00589
00590
00591
00592 PhysicsBody::ComponentListener::~ComponentListener() {
00593 if(KinematicJoint* kj = dynamic_cast<KinematicJoint*>(&comp)) {
00594 kj->removeBranchListener(this);
00595 kj->components.removeCollectionListener(this);
00596 }
00597 for(std::map<LinkComponent*, ComponentListener*>::iterator it=subComps.begin(); it!=subComps.end(); ++it)
00598 delete it->second;
00599 subComps.clear();
00600 freeBody();
00601 }
00602
00603 std::string PhysicsBody::ComponentListener::getPath() const {
00604 stringstream ss;
00605 if(const KinematicJoint* kj = dynamic_cast<const KinematicJoint*>(&comp)) {
00606 ss << kj->getPath() << ":" << getModel();
00607 } else if(parent!=NULL) {
00608 ss << parent->getPath() << "/" << getModel();
00609 } else {
00610 ss << "Free-" << getModel();
00611 }
00612 ss << "@" << ∁
00613 return ss.str();
00614 }
00615
00616 void PhysicsBody::ComponentListener::init() {
00617
00618
00619
00620 if(KinematicJoint* kj = dynamic_cast<KinematicJoint*>(&comp)) {
00621
00622 bool hasMass = kj->hasMass();
00623 bool hasCollision = hasCollisionShape(*kj);
00624 kj->components.addCollectionListener(this);
00625 kj->addBranchListener(this);
00626
00627
00628 if(body==NULL && ( (hasMass && hasCollision) || (parent==NULL && hasCollision) ) )
00629 allocBody();
00630
00631 plistCollectionEntriesChanged(kj->components);
00632 }
00633 }
00634
00635 void PhysicsBody::ComponentListener::allocBody() {
00636 ASSERTRET(body==NULL,"attempted to allocate a new body without freeing previous")
00637 btTransform tr(btTransform::getIdentity());
00638 if(bodyLocation!=NULL)
00639 tr.getOrigin() = btVector3((*bodyLocation)[0],(*bodyLocation)[1],(*bodyLocation)[2]) * world.spaceScale;
00640 if(bodyOrientation!=NULL) {
00641 fmat::Quaternion quat = fmat::Quaternion::fromAxis(*bodyOrientation);
00642 tr.setRotation(btQuaternion(quat.getX(),quat.getY(),quat.getZ(),quat.getW()));
00643 }
00644 PhysicsBody* bodyParent=NULL;
00645 if(parent!=NULL)
00646 bodyParent = &parent->findBody();
00647 KinematicJoint& kj = dynamic_cast<KinematicJoint&>(comp);
00648 plist::Primitive<float>* pos = (kj.outputOffset==plist::OutputSelector::UNUSED) ? NULL : &positions[kj.outputOffset.get()];
00649 ASSERT(body==NULL,"creating new body, already had one!?");
00650 body = new PhysicsBody(world, kj, pos, tr, bodyParent);
00651 updateListeners();
00652 }
00653
00654 void PhysicsBody::ComponentListener::freeBody() {
00655 if(body!=NULL) {
00656 delete collisionModelScaleListener; collisionModelScaleListener=NULL;
00657 delete collisionModelRotationListener; collisionModelRotationListener=NULL;
00658 delete collisionModelOffsetListener; collisionModelOffsetListener=NULL;
00659 delete centerOfMassListener; centerOfMassListener=NULL;
00660 delete body; body=NULL;
00661 }
00662 }
00663
00664 PhysicsBody& PhysicsBody::ComponentListener::findBody() {
00665 if(body!=NULL)
00666 return *body;
00667 if(parent==NULL) {
00668
00669 allocBody();
00670 return *body;
00671 }
00672 return parent->findBody();
00673 }
00674
00675 PhysicsBody::ComponentListener& PhysicsBody::ComponentListener::findLinkRoot() {
00676 if(dynamic_cast<KinematicJoint*>(&comp) || parent==NULL)
00677 return *this;
00678 ASSERT(dynamic_cast<KinematicJoint*>(&parent->comp),"Parent is not a kinematic joint?")
00679 return *parent;
00680 }
00681
00682 void PhysicsBody::ComponentListener::updateListeners() {
00683 delete collisionModelScaleListener; collisionModelScaleListener=NULL;
00684 delete collisionModelRotationListener; collisionModelRotationListener=NULL;
00685 delete collisionModelOffsetListener; collisionModelOffsetListener=NULL;
00686 delete centerOfMassListener; centerOfMassListener=NULL;
00687 PhysicsBody& b = findBody();
00688 if(comp.collisionModel=="Cube") {
00689 collisionModelScaleListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.collisionModelScale,b,&PhysicsBody::rebuild, false);
00690 collisionModelRotationListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.collisionModelRotation,b,&PhysicsBody::rebuild, false);
00691 collisionModelOffsetListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.collisionModelOffset,b,&PhysicsBody::rebuild, false);
00692 }
00693 if(comp.mass!=0)
00694 centerOfMassListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.centerOfMass,b,&PhysicsBody::rebuild, false);
00695 for(std::map<LinkComponent*, ComponentListener*>::iterator it=subComps.begin(); it!=subComps.end(); ++it)
00696 if(it->second->body==NULL)
00697 it->second->updateListeners();
00698 }
00699
00700 void PhysicsBody::ComponentListener::plistCollectionEntryAdded(plist::Collection& , plist::ObjectBase& entry) {
00701 LinkComponent& lc = dynamic_cast<LinkComponent&>(entry);
00702 ComponentListener * listener = new ComponentListener(world,lc,positions,this);
00703 subComps[&lc] = listener;
00704 if(listener->body==NULL && (lc.hasMass() || hasCollisionShape(lc)))
00705 rebuildBody();
00706 }
00707
00708 void PhysicsBody::ComponentListener::plistCollectionEntryRemoved(plist::Collection& , plist::ObjectBase& entry) {
00709 LinkComponent& lc = dynamic_cast<LinkComponent&>(entry);
00710 bool willBeMissed = (lc.hasMass() || hasCollisionShape(lc));
00711 std::map<LinkComponent*, ComponentListener*>::iterator it=subComps.find(&lc);
00712 if(it==subComps.end()) {
00713 std::cerr << "ERROR: PhysicsBody::LinkComponentListener could not find entry in component list for removed component" << std::endl;
00714 } else {
00715 delete it->second;
00716 subComps.erase(it);
00717 }
00718 if(willBeMissed)
00719 rebuildBody();
00720 }
00721
00722 void PhysicsBody::ComponentListener::plistCollectionEntriesChanged(plist::Collection& ) {
00723 size_t oldSize = subComps.size();
00724 for(std::map<LinkComponent*, ComponentListener*>::iterator it=subComps.begin(); it!=subComps.end(); ++it)
00725 delete it->second;
00726 subComps.clear();
00727 KinematicJoint& kj = dynamic_cast<KinematicJoint&>(comp);
00728 for(KinematicJoint::component_iterator it=kj.components.begin(); it!=kj.components.end(); ++it) {
00729 ComponentListener * cl = new ComponentListener(world,**it,positions,this);
00730 subComps[*it] = cl;
00731 }
00732 for(KinematicJoint::branch_iterator it=kj.getBranches().begin(); it!=kj.getBranches().end(); ++it) {
00733 ComponentListener * cl = new ComponentListener(world,**it,positions,this);
00734 subComps[*it] = cl;
00735 }
00736 if(oldSize!=0 || (subComps.size()!=0 && comp.hasMass() && hasCollisionShape(comp)))
00737 rebuildBody();
00738 }
00739
00740
00741 void PhysicsBody::ComponentListener::kinematicJointBranchAdded(KinematicJoint& kjparent, KinematicJoint& branch) {
00742 plistCollectionEntryAdded(kjparent, branch);
00743 }
00744
00745 void PhysicsBody::ComponentListener::kinematicJointBranchRemoved(KinematicJoint& kjparent, KinematicJoint& branch) {
00746 plistCollectionEntryRemoved(kjparent, branch);
00747 }
00748
00749 void PhysicsBody::ComponentListener::kinematicJointReconfigured(KinematicJoint& ) {}
00750
00751
00752 void PhysicsBody::ComponentListener::updateMass() {
00753 if(comp.mass==0) {
00754
00755 delete centerOfMassListener;
00756 centerOfMassListener=NULL;
00757
00758 if(parent!=NULL) {
00759
00760
00761 ComponentListener& l = findLinkRoot();
00762 if(l.body!=NULL) {
00763 if(!l.comp.hasMass() || !hasCollisionShape(l.comp)) {
00764 l.freeBody();
00765 }
00766 }
00767 }
00768 } else {
00769 if(centerOfMassListener==NULL)
00770 centerOfMassListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.centerOfMass,findBody(),&PhysicsBody::rebuild, false);
00771
00772 if(parent!=NULL) {
00773
00774 ComponentListener& l = findLinkRoot();
00775 if(l.body==NULL) {
00776 if(l.comp.hasMass() && hasCollisionShape(l.comp)) {
00777 rebuildBody();
00778 l.allocBody();
00779 return;
00780 }
00781 }
00782 }
00783 }
00784 rebuildBody();
00785 }
00786
00787 void PhysicsBody::ComponentListener::updateModel() {
00788 if(comp.collisionModel.size()==0) {
00789
00790 delete collisionModelScaleListener; collisionModelScaleListener=NULL;
00791 delete collisionModelRotationListener; collisionModelRotationListener=NULL;
00792 delete collisionModelOffsetListener; collisionModelOffsetListener=NULL;
00793
00794 if(parent!=NULL) {
00795
00796
00797 ComponentListener& l = findLinkRoot();
00798 if(l.body!=NULL) {
00799 if(!l.comp.hasMass() || !hasCollisionShape(l.comp)) {
00800 l.freeBody();
00801 }
00802 }
00803 }
00804 } else {
00805
00806 if(parent!=NULL) {
00807
00808 ComponentListener& l = findLinkRoot();
00809 if(l.body==NULL) {
00810 if(l.comp.hasMass() && hasCollisionShape(l.comp)) {
00811 rebuildBody();
00812 l.allocBody();
00813 return;
00814 }
00815 }
00816 }
00817 if(collisionModelOffsetListener==NULL) {
00818 PhysicsBody& b = findBody();
00819 collisionModelScaleListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.collisionModelScale,b,&PhysicsBody::rebuild, false);
00820 collisionModelRotationListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.collisionModelRotation,b,&PhysicsBody::rebuild, false);
00821 collisionModelOffsetListener = new plist::CollectionCallbackMember<PhysicsBody>(comp.collisionModelOffset,b,&PhysicsBody::rebuild, false);
00822 }
00823 }
00824 rebuildBody();
00825 }
00826
00827 bool PhysicsBody::ComponentListener::hasCollisionShape(const LinkComponent& c) {
00828 if(c.collisionModel.size()>0)
00829 return true;
00830 if(const KinematicJoint* kj = dynamic_cast<const KinematicJoint*>(&c)) {
00831 for(KinematicJoint::component_iterator it=kj->components.begin(); it!=kj->components.end(); ++it) {
00832 if((*it)->collisionModel.size()>0)
00833 return true;
00834 }
00835 for(KinematicJoint::branch_iterator it=kj->getBranches().begin(); it!=kj->getBranches().end(); ++it) {
00836 if(!(*it)->hasMass()) {
00837 if(hasCollisionShape(**it))
00838 return true;
00839 }
00840 }
00841 }
00842 return false;
00843 }
00844
00845
00846
00847 #ifdef HAVE_OGRE
00848 CollisionData::CollisionData(const std::string& meshName, Ogre::MeshPtr mesh)
00849 : name(meshName), vertices(NULL), indices(NULL)
00850 {
00851
00852 bool added_shared = false;
00853 size_t vertex_count=0, index_count=0;
00854 for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) {
00855 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
00856
00857 if(submesh->useSharedVertices) {
00858 if( !added_shared ) {
00859 vertex_count += mesh->sharedVertexData->vertexCount;
00860 added_shared = true;
00861 }
00862 } else {
00863 vertex_count += submesh->vertexData->vertexCount;
00864 }
00865
00866 index_count += submesh->indexData->indexCount;
00867 }
00868
00869
00870
00871 vertices = new float[vertex_count*3];
00872 indices = new unsigned int[index_count];
00873
00874
00875 added_shared = false;
00876 size_t current_offset = 0;
00877 size_t shared_offset = 0;
00878 size_t next_offset = 0;
00879 size_t index_offset = 0;
00880 for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) {
00881 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
00882
00883 Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
00884
00885 if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared)) {
00886 if(submesh->useSharedVertices) {
00887 added_shared = true;
00888 shared_offset = current_offset;
00889 }
00890
00891 const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
00892 Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
00893 unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
00894
00895 float* pReal;
00896 for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
00897 {
00898 posElem->baseVertexPointerToElement(vertex, &pReal);
00899 vertices[(current_offset + j)*3 + 0] = pReal[0]/1000;
00900 vertices[(current_offset + j)*3 + 1] = pReal[1]/1000;
00901 vertices[(current_offset + j)*3 + 2] = pReal[2]/1000;
00902
00903
00904
00905 }
00906
00907 vbuf->unlock();
00908 next_offset += vertex_data->vertexCount;
00909 }
00910
00911
00912 Ogre::IndexData* index_data = submesh->indexData;
00913 const size_t indexCnt = index_data->indexCount;
00914 Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
00915
00916 bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
00917
00918 unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
00919 unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
00920
00921 size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
00922
00923 if ( use32bitindexes ) {
00924 for ( size_t k = 0; k < indexCnt; k+=3) {
00925 indices[index_offset++] = pLong[k+0] + static_cast<unsigned long>(offset);
00926 indices[index_offset++] = pLong[k+1] + static_cast<unsigned long>(offset);
00927 indices[index_offset++] = pLong[k+2] + static_cast<unsigned long>(offset);
00928
00929 }
00930 } else {
00931 for ( size_t k = 0; k < indexCnt; k+=3) {
00932 indices[index_offset++] = static_cast<unsigned long>(pShort[k+0]) + static_cast<unsigned long>(offset);
00933 indices[index_offset++] = static_cast<unsigned long>(pShort[k+1]) + static_cast<unsigned long>(offset);
00934 indices[index_offset++] = static_cast<unsigned long>(pShort[k+2]) + static_cast<unsigned long>(offset);
00935
00936 }
00937 }
00938
00939 ibuf->unlock();
00940 current_offset = next_offset;
00941 }
00942
00943 std::cout << "Vertices: " << vertex_count << std::endl;
00944 for(unsigned int i=0; i<vertex_count; ++i)
00945 std::cout << vertices[i*3+0] << ' ' << vertices[i*3+1] << ' ' << vertices[i*3+2] << std::endl;
00946 std::cout << "Indices: " << index_count << std::endl;
00947 for(unsigned int i=0; i<index_count/3; ++i)
00948 std::cout << indices[i*3+0] << ' ' << indices[i*3+1] << ' ' << indices[i*3+2] << std::endl;
00949 }
00950 #endif
00951
00952 #endif // HAVE_BULLET
00953
00954
00955
00956
00957