| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- #include "Base.h"
- #include "Node.h"
- #include "PhysicsVehicle.h"
- #include "PhysicsVehicleWheel.h"
- namespace gameplay
- {
- PhysicsVehicleWheel::PhysicsVehicleWheel(Node* node, const PhysicsCollisionShape::Definition& shape, const PhysicsRigidBody::Parameters& parameters)
- : PhysicsCollisionObject(node)
- {
- // Note that the constructor for PhysicsRigidBody calls addCollisionObject and so
- // that is where the rigid body gets added to the dynamics world.
- _rigidBody = new PhysicsRigidBody(node, shape, parameters);
- findAncestorAndBind();
- }
- PhysicsVehicleWheel::PhysicsVehicleWheel(Node* node, PhysicsRigidBody* rigidBody)
- : PhysicsCollisionObject(node)
- {
- _rigidBody = rigidBody;
- findAncestorAndBind();
- }
- PhysicsVehicleWheel* PhysicsVehicleWheel::create(Node* node, Properties* properties)
- {
- // Note that the constructor for PhysicsRigidBody calls addCollisionObject and so
- // that is where the rigid body gets added to the dynamics world.
- PhysicsRigidBody* rigidBody = PhysicsRigidBody::create(node, properties, "VEHICLE_WHEEL");
- PhysicsVehicleWheel* wheel = new PhysicsVehicleWheel(node, rigidBody);
- // Load the defined wheel parameters.
- properties->rewind();
- Vector3 v;
- const char* name;
- while ((name = properties->getNextProperty()) != NULL)
- {
- if (strcmp(name, "steerable") == 0)
- {
- wheel->setSteerable(properties->getBool(name));
- }
- else if (strcmp(name, "wheelDirection") == 0 && properties->getVector3(name, &v))
- {
- wheel->setWheelDirection(v);
- }
- else if (strcmp(name, "wheelAxle") == 0 && properties->getVector3(name, &v))
- {
- wheel->setWheelAxle(v);
- }
- else if (strcmp(name, "strutConnectionOffset") == 0 && properties->getVector3(name, &v))
- {
- wheel->setStrutConnectionOffset(v);
- }
- else if (strcmp(name, "strutRestLength") == 0)
- {
- wheel->setStrutRestLength(properties->getFloat(name));
- }
- else if (strcmp(name, "strutTravelMax") == 0)
- {
- wheel->setStrutTravelMax(properties->getFloat(name));
- }
- else if (strcmp(name, "strutStiffness") == 0)
- {
- wheel->setStrutStiffness(properties->getFloat(name));
- }
- else if (strcmp(name, "strutDampingCompression") == 0)
- {
- wheel->setStrutDampingCompression(properties->getFloat(name));
- }
- else if (strcmp(name, "strutDampingRelaxation") == 0)
- {
- wheel->setStrutDampingRelaxation(properties->getFloat(name));
- }
- else if (strcmp(name, "strutForceMax") == 0)
- {
- wheel->setStrutForceMax(properties->getFloat(name));
- }
- else if (strcmp(name, "frictionBreakout") == 0)
- {
- wheel->setFrictionBreakout(properties->getFloat(name));
- }
- else if (strcmp(name, "wheelRadius") == 0)
- {
- wheel->setWheelRadius(properties->getFloat(name));
- }
- else if (strcmp(name, "rollInfluence") == 0)
- {
- wheel->setRollInfluence(properties->getFloat(name));
- }
- else
- {
- // Ignore this case (we've already parsed the rigid body parameters).
- }
- }
- return wheel;
- }
- PhysicsVehicleWheel::~PhysicsVehicleWheel()
- {
- SAFE_DELETE(_rigidBody);
- }
- btCollisionObject* PhysicsVehicleWheel::getCollisionObject() const
- {
- GP_ASSERT(_rigidBody);
- return _rigidBody->getCollisionObject();
- }
- PhysicsCollisionObject::Type PhysicsVehicleWheel::getType() const
- {
- return PhysicsCollisionObject::VEHICLE_WHEEL;
- }
- void PhysicsVehicleWheel::setEnabled(bool enable)
- {
- GP_ERROR("Operation not supported (PhysicsVehicleWheel::setEnabled(bool)). Use host vehicle instead.");
- }
- void PhysicsVehicleWheel::findAncestorAndBind()
- {
- GP_ASSERT(getNode());
- // This is not an efficient algorithm if the number of advertised
- // descendants gets large. In fact, this search is O(n*m) in the
- // worst case with n nodes and m advertised descendants per node.
- // But (1) we are only visiting ancestor nodes, and (2) the number
- // of advertised descendants is expected to be small since this
- // mechanism is currently only used for binding wheels onto a vehicle.
- //
- // TODO: revisit if the advertised descendants mechanism becomes popular.
- PhysicsVehicle* host = NULL;
- PhysicsCollisionObject* collisionObject;
- Node* m;
- for (Node* n = getNode()->getParent(); n && !host; n = n->getParent())
- {
- for (unsigned int i = 0; i < n->getNumAdvertisedDescendants() && !host; i++)
- {
- m = n->getAdvertisedDescendant(i);
- collisionObject = m->getCollisionObject();
- if (collisionObject && collisionObject->getType() == PhysicsCollisionObject::VEHICLE)
- {
- host = static_cast<PhysicsVehicle*>(collisionObject);
- }
- }
- }
- // Note: Currently this method is silent on failure to find a host.
- if (host)
- {
- host->addWheel(this);
- _initialOffset = _node->getTranslation() - host->_node->getTranslation();
- }
- }
- void PhysicsVehicleWheel::setHost(PhysicsVehicle* host, unsigned int indexInHost)
- {
- _host = host;
- _indexInHost = indexInHost;
- }
- void PhysicsVehicleWheel::addToVehicle(btRaycastVehicle* vehicle)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->getNumWheels() == vehicle->getNumWheels() + 1);
- // Use safe defaults for now. Properties are assigned elsewhere.
- btRaycastVehicle::btVehicleTuning tuning;
- vehicle->addWheel(
- btVector3(0, 0, 0),
- btVector3(0, -1, 0),
- btVector3(-1, 0, 0),
- 0.6f,
- 0.5f,
- tuning,
- false);
- }
- void PhysicsVehicleWheel::transform(Node* node) const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_node);
- node->setRotation(_orientation);
- // Use only the component parallel to the defined strut line
- Vector3 strutLine;
- getWheelDirection(&strutLine);
- _host->_node->getMatrix().transformVector(&strutLine);
- Vector3 wheelPos;
- getWheelPos(&wheelPos);
- node->setTranslation(wheelPos + strutLine*(strutLine.dot(_positionDelta) / strutLine.lengthSquared()));
- }
- void PhysicsVehicleWheel::update(float elapsedTime)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- const btTransform& trans = _host->_vehicle->getWheelInfo(_indexInHost).m_worldTransform;
- const btQuaternion& rot = trans.getRotation();
- const btVector3& pos = trans.getOrigin();
- _orientation.set(rot.x(), rot.y(), rot.z(), rot.w());
- Vector3 commandedPosition(pos.x(), pos.y(), pos.z());
- Vector3 wheelPos;
- getWheelPos(&wheelPos);
- commandedPosition -= wheelPos;
- // Filter out noise from Bullet
- Vector3 delta(_positionDelta, commandedPosition);
- float threshold = getStrutRestLength() * 2.0f;
- float responseTime = (delta.lengthSquared() > threshold*threshold) ? 0 : 60;
- _positionDelta.smooth(commandedPosition, elapsedTime, responseTime);
- }
- void PhysicsVehicleWheel::getConnectionDefault(Vector3* result) const
- {
- // projected strut length
- getWheelDirection(result);
- result->normalize();
- float length = 0.58f * getStrutRestLength();
- *result *= -length;
- // nudge wheel contact point to outer edge of tire for stability
- Vector3 nudge;
- getWheelAxle(&nudge);
- nudge *= nudge.dot(_initialOffset);
- nudge.normalize();
- *result += nudge * 0.068f * getWheelRadius(); // rough-in for tire width
- // offset at bind time
- *result += _initialOffset;
- }
- void PhysicsVehicleWheel::getWheelPos(Vector3* result) const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_node);
- *result = _initialOffset;
- _host->_node->getMatrix().transformPoint(result);
- }
- bool PhysicsVehicleWheel::isSteerable() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_bIsFrontWheel;
- }
- void PhysicsVehicleWheel::setSteerable(bool steerable)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_bIsFrontWheel = steerable;
- }
- void PhysicsVehicleWheel::getWheelDirection(Vector3* wheelDirection) const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- const btVector3& v = _host->_vehicle->getWheelInfo(_indexInHost).m_wheelDirectionCS;
- wheelDirection->set(v.x(), v.y(), v.z());
- }
- void PhysicsVehicleWheel::setWheelDirection(const Vector3& wheelDirection)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_wheelDirectionCS.setValue(wheelDirection.x, wheelDirection.y, wheelDirection.z);
- }
- void PhysicsVehicleWheel::getWheelAxle(Vector3* wheelAxle) const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- const btVector3& v = _host->_vehicle->getWheelInfo(_indexInHost).m_wheelAxleCS;
- wheelAxle->set(v.x(), v.y(), v.z());
- }
- void PhysicsVehicleWheel::setWheelAxle(const Vector3& wheelAxle)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_wheelAxleCS.setValue( wheelAxle.x, wheelAxle.y, wheelAxle.z);
- }
- void PhysicsVehicleWheel::getStrutConnectionOffset(Vector3* strutConnectionOffset) const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- const btVector3& v = _host->_vehicle->getWheelInfo(_indexInHost).m_chassisConnectionPointCS;
- strutConnectionOffset->set(v.x(), v.y(), v.z());
- Vector3 strutConnectionDefault;
- getConnectionDefault(&strutConnectionDefault);
- *strutConnectionOffset -= strutConnectionDefault;
- }
- void PhysicsVehicleWheel::setStrutConnectionOffset(const Vector3& strutConnectionOffset)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- Vector3 strutConnectionPoint;
- getConnectionDefault(&strutConnectionPoint);
- strutConnectionPoint += strutConnectionOffset;
- _host->_vehicle->getWheelInfo(_indexInHost).m_chassisConnectionPointCS.setValue(strutConnectionPoint.x,
- strutConnectionPoint.y,
- strutConnectionPoint.z);
- }
- float PhysicsVehicleWheel::getStrutRestLength() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionRestLength1;
- }
- void PhysicsVehicleWheel::setStrutRestLength(float strutRestLength)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionRestLength1 = strutRestLength;
- }
- float PhysicsVehicleWheel::getStrutTravelMax() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionTravelCm / 100.0f;
- }
- void PhysicsVehicleWheel::setStrutTravelMax(float strutTravelMax)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionTravelCm = strutTravelMax * 100.0f;
- }
- float PhysicsVehicleWheel::getStrutStiffness() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionStiffness;
- }
- void PhysicsVehicleWheel::setStrutStiffness(float strutStiffness)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionStiffness = strutStiffness;
- }
- float PhysicsVehicleWheel::getStrutDampingCompression() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingCompression;
- }
- void PhysicsVehicleWheel::setStrutDampingCompression(float strutDampingCompression)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingCompression = strutDampingCompression;
- }
- float PhysicsVehicleWheel::getStrutDampingRelaxation() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingRelaxation;
- }
- void PhysicsVehicleWheel::setStrutDampingRelaxation(float strutDampingRelaxation)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingRelaxation = strutDampingRelaxation;
- }
- float PhysicsVehicleWheel::getStrutForceMax() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionForce;
- }
- void PhysicsVehicleWheel::setStrutForceMax(float strutForceMax)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionForce = strutForceMax;
- }
- float PhysicsVehicleWheel::getFrictionBreakout() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_frictionSlip;
- }
- void PhysicsVehicleWheel::setFrictionBreakout(float frictionBreakout)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_frictionSlip = frictionBreakout;
- }
- float PhysicsVehicleWheel::getWheelRadius() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsRadius;
- }
- void PhysicsVehicleWheel::setWheelRadius(float wheelRadius)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsRadius = wheelRadius;
- }
- float PhysicsVehicleWheel::getRollInfluence() const
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- return _host->_vehicle->getWheelInfo(_indexInHost).m_rollInfluence;
- }
- void PhysicsVehicleWheel::setRollInfluence(float rollInfluence)
- {
- GP_ASSERT(_host);
- GP_ASSERT(_host->_vehicle);
- _host->_vehicle->getWheelInfo(_indexInHost).m_rollInfluence = rollInfluence;
- }
- }
|