diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 10ba446a8..da4ed70b0 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -636,7 +636,7 @@ void LinearWorld::moveKartAfterRescue(AbstractKart* kart) kart->getBody()->setCenterOfMassTransform(pos); //project kart to surface of track - bool kart_over_ground = m_physics->projectKartDownwards(kart); + bool kart_over_ground = m_track->findGround(kart); if (kart_over_ground) { @@ -645,6 +645,9 @@ void LinearWorld::moveKartAfterRescue(AbstractKart* kart) kart->getKartProperties()->getVertRescueOffset() * kart->getKartHeight(); kart->getBody()->translate(btVector3(0, vertical_offset, 0)); + // Also correctly set the graphics, otherwise the kart will + // be displayed for one frame at the incorrect position. + kart->updateGraphics(0, Vec3(0,0,0), btQuaternion(0, 0, 0, 1)); } else { @@ -653,7 +656,6 @@ void LinearWorld::moveKartAfterRescue(AbstractKart* kart) (kart->getIdent().c_str()), m_track->getIdent().c_str()); } - } // moveKartAfterRescue //----------------------------------------------------------------------------- diff --git a/src/modes/overworld.cpp b/src/modes/overworld.cpp index 14a498367..35c395d59 100644 --- a/src/modes/overworld.cpp +++ b/src/modes/overworld.cpp @@ -263,7 +263,7 @@ void OverWorld::moveKartAfterRescue(AbstractKart* kart, float angle) kart->getBody()->setCenterOfMassTransform(pos); //project kart to surface of track - bool kart_over_ground = m_physics->projectKartDownwards(kart); + bool kart_over_ground = m_track->findGround(kart); if (kart_over_ground) { diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index 9b08b8c95..0c086e0e4 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -258,7 +258,7 @@ void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) kart->getBody()->setCenterOfMassTransform(pos); //project kart to surface of track - bool kart_over_ground = m_physics->projectKartDownwards(kart); + bool kart_over_ground = m_track->findGround(kart); if (kart_over_ground) { diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index e102d6975..0da54b42b 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -542,7 +542,7 @@ void ThreeStrikesBattle::moveKartAfterRescue(AbstractKart* kart) kart->getBody()->setCenterOfMassTransform(pos); //project kart to surface of track - bool kart_over_ground = m_physics->projectKartDownwards(kart); + bool kart_over_ground = m_track->findGround(kart); if (kart_over_ground) { diff --git a/src/modes/tutorial_world.cpp b/src/modes/tutorial_world.cpp index e78f115e4..2f89f247a 100644 --- a/src/modes/tutorial_world.cpp +++ b/src/modes/tutorial_world.cpp @@ -38,7 +38,7 @@ void TutorialWorld::moveKartAfterRescue(AbstractKart* kart) kart->getBody()->setCenterOfMassTransform(pos); //project kart to surface of track - bool kart_over_ground = m_physics->projectKartDownwards(kart); + bool kart_over_ground = m_track->findGround(kart); if (kart_over_ground) { diff --git a/src/modes/world.cpp b/src/modes/world.cpp index a1735b602..e49c0a912 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -496,7 +496,8 @@ void World::resetAllKarts() pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), m_track->getAngle(quad)) ); kart->getBody()->setCenterOfMassTransform(pos); - bool kart_over_ground = m_physics->projectKartDownwards(kart); + + bool kart_over_ground = m_track->findGround(kart); if(kart_over_ground) { const Vec3 &xyz = kart->getTrans().getOrigin() @@ -541,7 +542,7 @@ void World::resetAllKarts() btVector3 up_offset(0, 0.5f * ((*i)->getKartHeight()), 0); (*i)->getVehicle()->getRigidBody()->translate (up_offset); - bool kart_over_ground = m_physics->projectKartDownwards(*i); + bool kart_over_ground = m_track->findGround(*i); if (!kart_over_ground) { diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 6b22ec73f..6cbefbd75 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -962,239 +962,3 @@ btScalar btKart::rayCast(btWheelInfo& wheel, const btVector3& ray) } // rayCast(btWheelInfo& wheel, const btVector3& ray // ---------------------------------------------------------------------------- -//Project vehicle onto surface in a particular direction. -//Used in reseting kart positions. -//Please align wheel direction with ray direction first. -bool btKart::projectVehicleToSurface(const btVector3& ray, - bool translate_vehicle) -{ - if (ray.length() <= btScalar(0)) - return false; - - btVector3 ray_dir = ray / ray.length(); - - for (int i=0;igetCenterOfMassTransform(); - btTransform rot_trans; - rot_trans.setIdentity(); - rot_trans.setRotation(trans.getRotation()); - rot_trans = rot_trans.inverse(); - - btTransform offset_trans; - offset_trans.setIdentity(); - btVector3 offset = min_wheel.m_raycastInfo.m_hardPointWS - + min_wheel.m_wheelsRadius * ray_dir; - offset -= getRigidBody()->getCenterOfMassPosition(); - offset_trans.setOrigin(rot_trans*offset); - - - // The effect of the following rotations is to make the 3 wheels with - // initial minimum distance to surface (in the ray direction) in contact - // with the plane between the points of intersection (between the ray and - // surface). - - //Note - For possible complex surfaces with lots of bumps directly under - // vehicle, the raycast needs to be done from a slightly higher - // above the surface. For such surfaces, the end result should be - // that at least 1 wheel touches the surface, and no wheel goes - // below the surface. - - //We need to rotate vehicle, using above contact point as a pivot to put - //2nd closest wheel nearer to the surface of the track - btScalar d_hpws = ( min_wheel.m_raycastInfo.m_hardPointWS - - min_wheel2.m_raycastInfo.m_hardPointWS).length(); - btScalar d_depth = ( min_wheel2.m_raycastInfo.m_contactPointWS - - min_wheel2.m_raycastInfo.m_hardPointWS - - ray_dir * min_wheel.m_wheelsRadius).length(); - d_depth -= min_depth; - - //calculate rotation angle from pivot point and plane perpendicular to ray - float rot_angle = atanf(d_depth / d_hpws); - rot_angle -= atanf((min_wheel2.m_wheelsRadius - min_wheel.m_wheelsRadius) - / d_hpws); - - getRigidBody()->setAngularVelocity(btVector3(0,0,0)); - getRigidBody()->setLinearVelocity(btVector3(0,0,0)); - - - btVector3 rot_axis = - ( min_wheel2.m_raycastInfo.m_hardPointWS - - min_wheel.m_raycastInfo.m_hardPointWS).cross(ray_dir); - - btTransform operator_trans; - operator_trans.setIdentity(); - - //perform pivot rotation - if (rot_axis.length() != btScalar(0)) - { - //rotate kart about pivot point, about line perpendicular to - //ray and vector between the 2 wheels - operator_trans *= offset_trans; - operator_trans.setRotation(btQuaternion(rot_trans*rot_axis.normalize(), - rot_angle)); - offset_trans.setOrigin(-(rot_trans*offset)); - operator_trans *= offset_trans; - } - - //apply tranform - trans *= operator_trans; - getRigidBody()->setCenterOfMassTransform(trans); - - //next, rotate about axis which is a vector between 2 wheels above, so that - //the 3rd wheel is correctly positioned. - - rot_axis = min_wheel2.m_raycastInfo.m_contactPointWS - - min_wheel.m_raycastInfo.m_contactPointWS; - btVector3 wheel_dist = min_wheel3.m_raycastInfo.m_hardPointWS - - min_wheel.m_raycastInfo.m_hardPointWS; - if (rot_axis.length() != btScalar(0)) - { - btVector3 proj = wheel_dist.dot(rot_axis) * rot_axis.normalize(); - - //calculate position on axis when a perpendicular line would go through - //3rd wheel position when translated in ray position and rotated as - // above - btVector3 pos_on_axis = - min_wheel.m_raycastInfo.m_contactPointWS + proj; - - btVector3 to_contact_pt = min_wheel3.m_raycastInfo.m_contactPointWS - - pos_on_axis; - btScalar dz = to_contact_pt.dot(ray_dir); - btScalar dw = (to_contact_pt - dz * ray_dir).length(); - rot_angle = atanf (dz / dw); - - btVector3 rot_point = getRigidBody()->getCenterOfMassPosition() - + min_depth * ray_dir - - min_wheel.m_raycastInfo.m_contactPointWS; - rot_point = rot_point.dot(rot_axis) * rot_axis.normalize() - rot_point; - - - //calculate translation offset to axis from center of mass along - // perpendicular - offset_trans.setIdentity(); - - offset= rot_point; - offset_trans.setOrigin(rot_trans*offset); - - btVector3 a = min_wheel3.m_raycastInfo.m_hardPointWS - - min_wheel.m_raycastInfo.m_hardPointWS; - btVector3 b = min_wheel2.m_raycastInfo.m_hardPointWS - - min_wheel.m_raycastInfo.m_hardPointWS; - - if ( (a.cross(b)).dot(ray_dir) > 0 ) - { - rot_angle *= btScalar(-1); - } - - //rotate about new axis - operator_trans.setIdentity(); - operator_trans *= offset_trans; - operator_trans.setRotation(btQuaternion(rot_trans*rot_axis.normalize(), - rot_angle)); - offset_trans.setOrigin(-(rot_trans*offset)); - operator_trans *= offset_trans; - - //apply tranform - trans *= operator_trans; - getRigidBody()->setCenterOfMassTransform(trans); - } - - if (!translate_vehicle) - return true; - - - for (int i=0;itranslate((min_depth) * ray_dir); - //offset for suspension rest length - getRigidBody()->translate(-min_wheel.getSuspensionRestLength() * - min_wheel.m_raycastInfo.m_wheelDirectionWS); - return true; -} // projectVehicleToSurface diff --git a/src/physics/btKart.hpp b/src/physics/btKart.hpp index 67f884b2d..6f1945fb7 100644 --- a/src/physics/btKart.hpp +++ b/src/physics/btKart.hpp @@ -169,8 +169,6 @@ public: void setSliding(bool active); void instantSpeedIncreaseTo(float speed); void capSpeed(float max_speed); - bool projectVehicleToSurface(const btVector3& ray, - bool translate_vehicle); // ------------------------------------------------------------------------ /** btActionInterface interface. */ diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 18104a039..eb4d81605 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -248,18 +248,6 @@ void Physics::update(float dt) m_karts_to_delete.clear(); } // update -//----------------------------------------------------------------------------- -/** Project all karts downwards onto the surface below. - * Used in setting the starting positions of all the karts. - */ - -bool Physics::projectKartDownwards(const AbstractKart *k) -{ - btVector3 hell(0, -10000, 0); - return k->getVehicle()->projectVehicleToSurface(hell, - /*allow translation*/true); -} //projectKartsDownwards - //----------------------------------------------------------------------------- /** Handles the special case of two karts colliding with each other, which * means that bombs must be passed on. If both karts have a bomb, they'll diff --git a/src/physics/physics.hpp b/src/physics/physics.hpp index 7d76a33b7..9b160aed0 100644 --- a/src/physics/physics.hpp +++ b/src/physics/physics.hpp @@ -164,7 +164,6 @@ public: void nextDebugMode () {m_debug_drawer->nextDebugMode(); } /** Returns true if the debug drawer is enabled. */ bool isDebug() const {return m_debug_drawer->debugEnabled(); } - bool projectKartDownwards(const AbstractKart *k); virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold,int numManifolds, btTypedConstraint** constraints,int numConstraints, diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 8184290e2..5fa342cbe 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -47,6 +47,8 @@ using namespace irr; #include "io/xml_node.hpp" #include "items/item.hpp" #include "items/item_manager.hpp" +#include "karts/abstract_kart.hpp" +#include "karts/kart_properties.hpp" #include "modes/linear_world.hpp" #include "modes/easter_egg_hunt.hpp" #include "modes/world.hpp" @@ -2004,3 +2006,65 @@ const core::vector3df& Track::getSunRotation() { return m_sun->getRotation(); } +//----------------------------------------------------------------------------- +/** Determines if the kart is over ground. + * Used in setting the starting positions of all the karts. + * \param k The kart to project downward. + * \return True of the kart is on terrain. + */ + +bool Track::findGround(AbstractKart *kart) +{ + btVector3 to(kart->getXYZ()); + to.setY(-100000.f); + + // Material and hit point are not needed; + const Material *m; + Vec3 hit_point, normal; + bool over_ground = m_track_mesh->castRay(kart->getXYZ(), to, &hit_point, + &m, &normal); + const Vec3 &xyz = kart->getXYZ(); + if(!over_ground || !m) + { + Log::warn("physics", "Kart at (%f %f %f) can not be dropped.", + xyz.getX(),xyz.getY(),xyz.getZ()); + return false; + } + + // Check if the material the kart is about to be placed on would trigger + // a reset. If so, this is not a valid position. + if(m->isDriveReset()) + { + Log::warn("physics","Kart at (%f %f %f) over reset terrain '%s'", + xyz.getX(),xyz.getY(),xyz.getZ(), + m->getTexFname().c_str()); + return false; + } + + // See if the kart is too high above the ground - it would drop + // too long. + if(xyz.getY() - hit_point.getY() > 5) + { + Log::warn("physics", + "Kart at (%f %f %f) is too high above ground at (%f %f %f)", + xyz.getX(),xyz.getY(),xyz.getZ(), + hit_point.getX(),hit_point.getY(),hit_point.getZ()); + return false; + } + + + btTransform t = kart->getBody()->getCenterOfMassTransform(); + // The computer offset is slightly too large, it should take + // the default suspension rest insteat of suspension rest (i.e. the + // length of the suspension with the weight of the kart resting on + // it). On the other hand this initial bouncing looks nice imho + // - so I'll leave it in for now. + float offset = kart->getKartProperties()->getSuspensionRest() + + kart->getKartProperties()->getWheelRadius(); + t.setOrigin(hit_point+Vec3(0, offset, 0) ); + kart->getBody()->setCenterOfMassTransform(t); + kart->setTrans(t); + + return true; +} // findGround + diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 5a134b95d..1fb7caa89 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -402,8 +402,9 @@ public: bool secondary_hits=true) const; void loadTrackModel (bool reverse_track = false, unsigned int mode_id=0); - std::vector< std::vector > - buildHeightMap(); + bool findGround(AbstractKart *kart); + + std::vector< std::vector > buildHeightMap(); // ------------------------------------------------------------------------ /** Returns the texture with the mini map for this track. */ const video::ITexture* getMiniMap () const { return m_mini_map; }