From dbec3ae30ae2a4e5b906470f2663ed4d5f7508db Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 8 Nov 2011 12:16:40 +0000 Subject: [PATCH 02/68] Replaced btKart with a fresh copy of bullet's raycast vehicle (i.e. all STK specific tuning was removed). STK callbacks for zipper and sliding are empty, only projectVehicleToSurface was added back in. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10144 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/kart.cpp | 12 +- src/karts/kart.hpp | 4 +- src/physics/btKart.cpp | 1260 +++++++++++++++++++-------------- src/physics/btKart.hpp | 279 ++++++-- src/physics/btKartRaycast.hpp | 4 +- 5 files changed, 978 insertions(+), 581 deletions(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 08f3ba3d1..bc8f46cd6 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -278,8 +278,8 @@ void Kart::createPhysics() new btKartRaycaster(World::getWorld()->getPhysics()->getPhysicsWorld()); m_tuning = new btKart::btVehicleTuning(); m_tuning->m_maxSuspensionTravelCm = m_kart_properties->getSuspensionTravelCM(); - m_vehicle = new btKart(*m_tuning, m_body, m_vehicle_raycaster, - m_kart_properties->getTrackConnectionAccel()); + m_vehicle = new btKart(*m_tuning, m_body, m_vehicle_raycaster); + //FIXMEJH m_kart_properties->getTrackConnectionAccel()); // never deactivate the vehicle m_body->setActivationState(DISABLE_DEACTIVATION); @@ -1724,7 +1724,7 @@ void Kart::updatePhysics(float dt) // you have full traction; above 0.5 rad angles you have absolutely none; // inbetween there is a linear change in friction float friction = 1.0f; - bool enable_skidding = false; + bool enable_sliding = false; // This way the current skidding // handling can be disabled for certain material (e.g. the @@ -1744,7 +1744,7 @@ void Kart::updatePhysics(float dt) if (distanceFromUp < 0.85f) { friction = 0.0f; - enable_skidding = true; + enable_sliding = true; } else if (distanceFromUp > 0.9f) { @@ -1753,7 +1753,7 @@ void Kart::updatePhysics(float dt) else { friction = (distanceFromUp - 0.85f) / 0.5f; - enable_skidding = true; + enable_sliding = true; } } @@ -1763,7 +1763,7 @@ void Kart::updatePhysics(float dt) wheel.m_frictionSlip = friction*m_kart_properties->getFrictionSlip(); } - m_vehicle->enableSliding(enable_skidding); + m_vehicle->setSliding(enable_sliding); float steering = getMaxSteerAngle() * m_controls.m_steer*m_skidding; diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 273d92b2c..b7a97604a 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -38,6 +38,7 @@ #include "karts/moveable.hpp" #include "karts/kart_model.hpp" #include "karts/kart_properties.hpp" +#include "physics/btKart.hpp" #include "tracks/terrain_info.hpp" #include "utils/no_copy.hpp" @@ -133,8 +134,7 @@ private: // Bullet physics parameters // ------------------------- - btRaycastVehicle::btVehicleTuning - *m_tuning; + btKart::btVehicleTuning *m_tuning; btCompoundShape m_kart_chassis; btVehicleRaycaster *m_vehicle_raycaster; btKart *m_vehicle; diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 493a8fa3c..3e4250729 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -4,138 +4,766 @@ * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies. - * Erwin Coumans makes no representations about the suitability - * of this software for any purpose. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. * It is provided "as is" without express or implied warranty. */ -/* Based on btRayCastVehicle, but modified for STK. - * projectVehicleToSurface function and shorter raycast functions added. - */ - -#include "physics/btKart.hpp" - -#include "LinearMath/btMinMax.h" #include "LinearMath/btVector3.h" -#include "LinearMath/btQuaternion.h" +#include "btKart.hpp" + #include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h" #include "BulletDynamics/ConstraintSolver/btJacobianEntry.h" +#include "LinearMath/btQuaternion.h" #include "BulletDynamics/Dynamics/btDynamicsWorld.h" #include "BulletDynamics/Vehicle/btVehicleRaycaster.h" #include "BulletDynamics/Vehicle/btWheelInfo.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btIDebugDraw.h" #include "BulletDynamics/ConstraintSolver/btContactConstraint.h" -struct btWheelContactPoint; -btScalar calcRollingFriction(btWheelContactPoint& contactPoint); +#define ROLLING_INFLUENCE_FIX -btKart::btKart(const btVehicleTuning& tuning,btRigidBody* chassis, - btVehicleRaycaster* raycaster, float track_connect_accel ) -: btRaycastVehicle(tuning, chassis, raycaster) +btRigidBody& btActionInterface::getFixedBody() { - m_track_connect_accel = track_connect_accel; - - m_num_wheels_on_ground = 0; - - m_zipper_active = false; - m_zipper_velocity = btScalar(0); - m_allow_sliding = false; + static btRigidBody s_fixed(0, 0,0); + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + return s_fixed; } -// ---------------------------------------------------------------------------- +btKart::btKart(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) +:m_vehicleRaycaster(raycaster), +m_pitchControl(btScalar(0.)) +{ + m_chassisBody = chassis; + m_indexRightAxis = 0; + m_indexUpAxis = 2; + m_indexForwardAxis = 1; + defaultInit(tuning); + m_num_wheels_on_ground = 0; +} + + +void btKart::defaultInit(const btVehicleTuning& tuning) +{ + (void)tuning; + m_currentVehicleSpeedKmHour = btScalar(0.); + m_steeringValue = btScalar(0.); + +} + + + btKart::~btKart() { } -// ---------------------------------------------------------------------------- -btScalar btKart::rayCast(btWheelInfo& wheel) + +// +// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed +// +btWheelInfo& btKart::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel) { - updateWheelTransformsWS( wheel,false); + btWheelInfoConstructionInfo ci; - btScalar depth = -1; + ci.m_chassisConnectionCS = connectionPointCS; + ci.m_wheelDirectionCS = wheelDirectionCS0; + ci.m_wheelAxleCS = wheelAxleCS; + ci.m_suspensionRestLength = suspensionRestLength; + ci.m_wheelRadius = wheelRadius; + ci.m_suspensionStiffness = tuning.m_suspensionStiffness; + ci.m_wheelsDampingCompression = tuning.m_suspensionCompression; + ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping; + ci.m_frictionSlip = tuning.m_frictionSlip; + ci.m_bIsFrontWheel = isFrontWheel; + ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm; + ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce; - btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius+ - wheel.m_maxSuspensionTravelCm*0.01f; - - btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); - const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; - wheel.m_raycastInfo.m_contactPointWS = source + rayvector; - const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; - - btScalar param = btScalar(0.); - - btVehicleRaycaster::btVehicleRaycasterResult rayResults; - - assert(m_vehicleRaycaster); - - void* object = m_vehicleRaycaster->castRay(source,target,rayResults); - - wheel.m_raycastInfo.m_groundObject = 0; - - if (object) - { - param = rayResults.m_distFraction; - depth = raylen * rayResults.m_distFraction; - wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; - wheel.m_raycastInfo.m_isInContact = true; - - wheel.m_raycastInfo.m_groundObject = &getFixedBody();//todo for driving on dynamic/movable objects!; - //wheel.m_raycastInfo.m_groundObject = object; - - - btScalar hitDistance = param*raylen; - wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; - //clamp on max suspension travel - - btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01); - btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01); - if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) - { - wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; - } - if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) - { - wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; - } - - wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; - - btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); - - btVector3 chassis_velocity_at_contactPoint; - btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); - - chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); - - btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); - - if ( denominator >= btScalar(-0.1)) - { - wheel.m_suspensionRelativeVelocity = btScalar(0.0); - wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); - } - else - { - btScalar inv = btScalar(-1.) / denominator; - wheel.m_suspensionRelativeVelocity = projVel * inv; - wheel.m_clippedInvContactDotSuspension = inv; - } - - } else - { - //put wheel info as in rest position - wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); - wheel.m_suspensionRelativeVelocity = btScalar(0.0); - wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; - wheel.m_clippedInvContactDotSuspension = btScalar(1.0); - - } - - return depth; + m_wheelInfo.push_back( btWheelInfo(ci)); + + btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1]; + + updateWheelTransformsWS( wheel , false ); + updateWheelTransform(getNumWheels()-1,false); + return wheel; } + + +const btTransform& btKart::getWheelTransformWS( int wheelIndex ) const +{ + btAssert(wheelIndex < getNumWheels()); + const btWheelInfo& wheel = m_wheelInfo[wheelIndex]; + return wheel.m_worldTransform; + +} + +void btKart::updateWheelTransform( int wheelIndex , bool interpolatedTransform) +{ + + btWheelInfo& wheel = m_wheelInfo[ wheelIndex ]; + updateWheelTransformsWS(wheel,interpolatedTransform); + btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS; + const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS; + btVector3 fwd = up.cross(right); + fwd = fwd.normalize(); +// up = right.cross(fwd); +// up.normalize(); + + //rotate around steering over de wheelAxleWS + btScalar steering = wheel.m_steering; + + btQuaternion steeringOrn(up,steering);//wheel.m_steering); + btMatrix3x3 steeringMat(steeringOrn); + + btQuaternion rotatingOrn(right,-wheel.m_rotation); + btMatrix3x3 rotatingMat(rotatingOrn); + + btMatrix3x3 basis2( + right[0],fwd[0],up[0], + right[1],fwd[1],up[1], + right[2],fwd[2],up[2] + ); + + wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2); + wheel.m_worldTransform.setOrigin( + wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength + ); +} + +void btKart::resetSuspension() +{ + + int i; + for (i=0;igetMotionState())) + { + getRigidBody()->getMotionState()->getWorldTransform(chassisTrans); + } + + wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS ); + wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ; + wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS; +} + +btScalar btKart::rayCast(btWheelInfo& wheel) +{ + updateWheelTransformsWS( wheel,false); + + + btScalar depth = -1; + + btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius; + + btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); + const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; + wheel.m_raycastInfo.m_contactPointWS = source + rayvector; + const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; + + btScalar param = btScalar(0.); + + btVehicleRaycaster::btVehicleRaycasterResult rayResults; + + btAssert(m_vehicleRaycaster); + + void* object = m_vehicleRaycaster->castRay(source,target,rayResults); + + wheel.m_raycastInfo.m_groundObject = 0; + + if (object) + { + param = rayResults.m_distFraction; + depth = raylen * rayResults.m_distFraction; + wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; + wheel.m_raycastInfo.m_isInContact = true; + + wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!; + //wheel.m_raycastInfo.m_groundObject = object; + + + btScalar hitDistance = param*raylen; + wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; + //clamp on max suspension travel + + btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01); + btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01); + if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; + } + if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; + } + + wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; + + btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); + + btVector3 chassis_velocity_at_contactPoint; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); + + chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); + + btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); + + if ( denominator >= btScalar(-0.1)) + { + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); + } + else + { + btScalar inv = btScalar(-1.) / denominator; + wheel.m_suspensionRelativeVelocity = projVel * inv; + wheel.m_clippedInvContactDotSuspension = inv; + } + + } else + { + //put wheel info as in rest position + wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; + wheel.m_clippedInvContactDotSuspension = btScalar(1.0); + } + + return depth; +} + + +const btTransform& btKart::getChassisWorldTransform() const +{ + /*if (getRigidBody()->getMotionState()) + { + btTransform chassisWorldTrans; + getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans); + return chassisWorldTrans; + } + */ + + + return getRigidBody()->getCenterOfMassTransform(); +} + + +void btKart::updateVehicle( btScalar step ) +{ + { + for (int i=0;igetLinearVelocity().length(); + + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.)) + { + m_currentVehicleSpeedKmHour *= btScalar(-1.); + } + + // + // simulate suspension + // + + int i=0; + m_num_wheels_on_ground = 0; + for (i=0;i wheel.m_maxSuspensionForce) + { + suspensionForce = wheel.m_maxSuspensionForce; + } + btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition(); + + getRigidBody()->applyImpulse(impulse, relpos); + + } + + + + updateFriction( step); + + + for (i=0;igetCenterOfMassPosition(); + btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos ); + + if (wheel.m_raycastInfo.m_isInContact) + { + const btTransform& chassisWorldTransform = getChassisWorldTransform(); + + btVector3 fwd ( + chassisWorldTransform.getBasis()[0][m_indexForwardAxis], + chassisWorldTransform.getBasis()[1][m_indexForwardAxis], + chassisWorldTransform.getBasis()[2][m_indexForwardAxis]); + + btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS); + fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj; + + btScalar proj2 = fwd.dot(vel); + + wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius); + wheel.m_rotation += wheel.m_deltaRotation; + + } else + { + wheel.m_rotation += wheel.m_deltaRotation; + } + + wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact + + } + + + +} + + +void btKart::setSteeringValue(btScalar steering,int wheel) +{ + btAssert(wheel>=0 && wheel < getNumWheels()); + + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_steering = steering; +} + + + +btScalar btKart::getSteeringValue(int wheel) const +{ + return getWheelInfo(wheel).m_steering; +} + + +void btKart::applyEngineForce(btScalar force, int wheel) +{ + btAssert(wheel>=0 && wheel < getNumWheels()); + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_engineForce = force; +} + + +const btWheelInfo& btKart::getWheelInfo(int index) const +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +btWheelInfo& btKart::getWheelInfo(int index) +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +void btKart::setBrake(btScalar brake,int wheelIndex) +{ + btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels())); + getWheelInfo(wheelIndex).m_brake = brake; +} + + +void btKart::updateSuspension(btScalar deltaTime) +{ + (void)deltaTime; + + btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass(); + + for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar relaxation = 1.f; + m_jacDiagABInv = relaxation/(denom0+denom1); + } + + + +}; + +btScalar calcRollingFriction(btWheelContactPoint& contactPoint); +btScalar calcRollingFriction(btWheelContactPoint& contactPoint) +{ + + btScalar j1=0.f; + + const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld; + + btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); + btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition(); + + btScalar maxImpulse = contactPoint.m_maxImpulse; + + btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel); + + // calculate j that moves us to zero relative velocity + j1 = -vrel * contactPoint.m_jacDiagABInv; + btSetMin(j1, maxImpulse); + btSetMax(j1, -maxImpulse); + + return j1; +} + + + + +btScalar sideFrictionStiffness2 = btScalar(1.0); +void btKart::updateFriction(btScalar timeStep) +{ + + //calculate the impulse, so that the wheels don't move sidewards + int numWheel = getNumWheels(); + if (!numWheel) + return; + + m_forwardWS.resize(numWheel); + m_axle.resize(numWheel); + m_forwardImpulse.resize(numWheel); + m_sideImpulse.resize(numWheel); + + int numWheelsOnGround = 0; + + + //collapse all those loops into one! + for (int i=0;i maximpSquared) + { + sliding = true; + + btScalar factor = maximp / btSqrt(impulseSquared); + + m_wheelInfo[wheel].m_skidInfo *= factor; + } + } + + } + } + + + + + if (sliding) + { + for (int wheel = 0;wheel < getNumWheels(); wheel++) + { + if (m_sideImpulse[wheel] != btScalar(0.)) + { + if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) + { + m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + } + } + } + } + + // apply the impulses + { + for (int wheel = 0;wheelgetCenterOfMassPosition(); + + if (m_forwardImpulse[wheel] != btScalar(0.)) + { + m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); + } + if (m_sideImpulse[wheel] != btScalar(0.)) + { + class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; + + btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - + groundObject->getCenterOfMassPosition(); + + + btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; + +#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT. + btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis); + rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence)); +#else + rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence; +#endif + m_chassisBody->applyImpulse(sideImp,rel_pos); + + //apply friction impulse on the ground + groundObject->applyImpulse(-sideImp,rel_pos2); + } + } + } + + +} + + + +void btKart::debugDraw(btIDebugDraw* debugDrawer) +{ + + for (int v=0;vgetNumWheels();v++) + { + btVector3 wheelColor(0,1,1); + if (getWheelInfo(v).m_raycastInfo.m_isInContact) + { + wheelColor.setValue(0,0,1); + } else + { + wheelColor.setValue(1,0,1); + } + + btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin(); + + btVector3 axle = btVector3( + getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]); + + //debug wheels (cylinders) + debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); + debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); + + } +} + + +// ---------------------------------------------------------------------------- +void btKart::setSliding(bool active) +{ +} // setSliding + +// ---------------------------------------------------------------------------- +void btKart::activateZipper(float speed) +{ +} // activateZipper + +// ---------------------------------------------------------------------------- +void btKart::deactivateZipper() +{ +} // deactivateZipper + // ---------------------------------------------------------------------------- //Shorter version of above raycast function. This is used when projecting //vehicles towards the ground at the start of a race @@ -167,13 +795,14 @@ btScalar btKart::rayCast(btWheelInfo& wheel, const btVector3& ray) } return depth; -} +} // 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) +bool btKart::projectVehicleToSurface(const btVector3& ray, + bool translate_vehicle) { if (ray.length() <= btScalar(0)) return false; @@ -383,419 +1012,4 @@ bool btKart::projectVehicleToSurface(const btVector3& ray, bool translate_vehicl getRigidBody()->translate(-min_wheel.getSuspensionRestLength() * min_wheel.m_raycastInfo.m_wheelDirectionWS); return true; -} - - -// ---------------------------------------------------------------------------- -void btKart::updateVehicle( btScalar step ) -{ - { - for (int i=0;igetLinearVelocity().length(); - - const btTransform& chassisTrans = getChassisWorldTransform(); - - btVector3 forwardW ( - chassisTrans.getBasis()[0][m_indexForwardAxis], - chassisTrans.getBasis()[1][m_indexForwardAxis], - chassisTrans.getBasis()[2][m_indexForwardAxis]); - - if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.)) - { - m_currentVehicleSpeedKmHour *= btScalar(-1.); - } - - // - // simulate suspension - // - - int i=0; - m_num_wheels_on_ground = 0; - - for (i=0;i gMaxSuspensionForce) - { - suspensionForce = gMaxSuspensionForce; - } - btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; - btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition(); - - getRigidBody()->applyImpulse(impulse, relpos); - } - - - updateFriction( step); - - - for (i=0;igetCenterOfMassPosition(); - btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos ); - - if (wheel.m_raycastInfo.m_isInContact) - { - const btTransform& chassisWorldTransform = getChassisWorldTransform(); - - btVector3 fwd ( - chassisWorldTransform.getBasis()[0][m_indexForwardAxis], - chassisWorldTransform.getBasis()[1][m_indexForwardAxis], - chassisWorldTransform.getBasis()[2][m_indexForwardAxis]); - - btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS); - fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj; - - btScalar proj2 = fwd.dot(vel); - - wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius); - wheel.m_rotation += wheel.m_deltaRotation; - - } else - { - wheel.m_rotation += wheel.m_deltaRotation; - } - - wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact - - } - -} - -// ---------------------------------------------------------------------------- -void btKart::updateSuspension(btScalar deltaTime) -{ - (void)deltaTime; - - btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass(); - - for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); - btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); - btScalar relaxation = 1.f; - m_jacDiagABInv = relaxation/(denom0+denom1); - } - - -}; - -// ---------------------------------------------------------------------------- -void btKart::updateFriction(btScalar timeStep) -{ - - //calculate the impulse, so that the wheels don't move sidewards - int numWheel = getNumWheels(); - if (!numWheel) - return; - - m_forwardWS.resize(numWheel); - m_axle.resize(numWheel); - m_forwardImpulse.resize(numWheel); - m_sideImpulse.resize(numWheel); - - - //collapse all those loops into one! - for (int i=0;igetLinearVelocity().length()) / m_chassisBody->getInvMass(); - } - } - else - { - - if (wheelInfo.m_engineForce != 0.f) - { - rollingFriction = wheelInfo.m_engineForce* timeStep; - } else - { - //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break) - btScalar defaultRollingFrictionImpulse = 0.f; - btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse; - btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse); - rollingFriction = calcRollingFriction(contactPt); - // This is a work around for the problem that a kart shakes - // if it is braking: we get a minor impulse forward, which - // bullet then tries to offset by applying a backward - // impulse - which is a bit too big, causing a impulse - // backwards, ... till the kart is shaking backwards and - // forwards - if(wheelInfo.m_brake && fabsf(rollingFriction)<10) - rollingFriction=0; - } - - m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; - } - btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip; - btScalar maximpSide = maximp; - - btScalar maximpSquared = maximp * maximpSide; - - btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor; - btScalar y = (m_sideImpulse[wheel] ) * sideFactor; - - btScalar impulseSquared = (x*x + y*y); - - if (impulseSquared > maximpSquared) - { - sliding = true; - - btScalar factor = maximp / btSqrt(impulseSquared); - - m_wheelInfo[wheel].m_skidInfo *= factor; - } - } // if groundObject - - } // for wheelgetCenterOfMassPosition(); - - if (m_forwardImpulse[wheel] != btScalar(0.)) - { - m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]), - btVector3(0,0,0)); - } - if (m_sideImpulse[wheel] != btScalar(0.)) - { - class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; - - btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - - groundObject->getCenterOfMassPosition(); - - //adjust relative position above ground so that force only acts sideways - btVector3 delta_vec = (wheelInfo.m_raycastInfo.m_hardPointWS - wheelInfo.m_raycastInfo.m_contactPointWS); - if (delta_vec.length() != btScalar (0)) - { - delta_vec = delta_vec.normalize(); - rel_pos -= delta_vec * rel_pos.dot(delta_vec); - } - - btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; - - rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence; - m_chassisBody->applyImpulse(sideImp,rel_pos); - - //apply friction impulse on the ground - groundObject->applyImpulse(-sideImp,rel_pos2); - } - } - } - - -} +} // projectVehicleToSurface diff --git a/src/physics/btKart.hpp b/src/physics/btKart.hpp index e860ffc38..060eb2993 100644 --- a/src/physics/btKart.hpp +++ b/src/physics/btKart.hpp @@ -4,61 +4,244 @@ * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies. - * Erwin Coumans makes no representations about the suitability - * of this software for any purpose. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. * It is provided "as is" without express or implied warranty. */ -#ifndef HEADER_BT_KART_HPP -#define HEADER_BT_KART_HPP - -#include "btBulletDynamicsCommon.h" +#ifndef BT_KART_HPP +#define BT_KART_HPP +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "btkartRaycast.hpp" class btDynamicsWorld; -struct btWheelInfo; +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletDynamics/Vehicle/btWheelInfo.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" -/** The btKart is a raycast vehicle, that does not skid. It therefore solves - * the problems with the plain bullet physics that karts would often rotate - * on a spot if one of the wheels loses contact with the ground. - * \ingroup physics - */ -class btKart : public btRaycastVehicle +class btVehicleTuning; + +///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. +class btKart : public btActionInterface { - void defaultInit(const btVehicleTuning& tuning); - btScalar m_track_connect_accel; - int m_num_wheels_on_ground; - bool m_zipper_active; - btScalar m_zipper_velocity; - - /** Sliding (skidding) will only be permited when this is true. Also check - * the friction parameter in the wheels since friction directly affects skidding - */ - bool m_allow_sliding; - +protected: + btAlignedObjectArray m_forwardWS; + btAlignedObjectArray m_axle; + btAlignedObjectArray m_forwardImpulse; + btAlignedObjectArray m_sideImpulse; + + ///backwards compatibility + int m_userConstraintType; + int m_userConstraintId; + public: - - btKart(const btVehicleTuning& tuning,btRigidBody* chassis, - btVehicleRaycaster* raycaster, float track_connect_accel ); - virtual ~btKart() ; - btScalar rayCast(btWheelInfo& wheel); - btScalar rayCast(btWheelInfo& wheel, const btVector3& ray); - bool projectVehicleToSurface(const btVector3& ray, bool translate_vehicle); - virtual void updateVehicle(btScalar step); - void resetSuspension(); - int getNumWheelsOnGround() const { return m_num_wheels_on_ground; } - void setRaycastWheelInfo(int wheelIndex , bool isInContact, - const btVector3& hitPoint, - const btVector3& hitNormal,btScalar depth); - void setPitchControl(btScalar pitch) { m_pitchControl = pitch; } - void activateZipper(btScalar vel) { m_zipper_active = true; m_zipper_velocity = vel; } - void deactivateZipper() { m_zipper_active = false; } - void updateSuspension(btScalar deltaTime); - virtual void updateFriction(btScalar timeStep); - - /** Sliding (skidding) will only be permited when this is set to true. Also check - * the friction parameter in the wheels since friction directly affects skidding - */ - void enableSliding(bool enabled) { m_allow_sliding = enabled; } + class btVehicleTuning + { + public: + + btVehicleTuning() + :m_suspensionStiffness(btScalar(5.88)), + m_suspensionCompression(btScalar(0.83)), + m_suspensionDamping(btScalar(0.88)), + m_maxSuspensionTravelCm(btScalar(500.)), + m_frictionSlip(btScalar(10.5)), + m_maxSuspensionForce(btScalar(6000.)) + { + } + btScalar m_suspensionStiffness; + btScalar m_suspensionCompression; + btScalar m_suspensionDamping; + btScalar m_maxSuspensionTravelCm; + btScalar m_frictionSlip; + btScalar m_maxSuspensionForce; + + }; +protected: + + btScalar m_tau; + btScalar m_damping; + btVehicleRaycaster* m_vehicleRaycaster; + btScalar m_pitchControl; + btScalar m_steeringValue; + btScalar m_currentVehicleSpeedKmHour; + + btRigidBody* m_chassisBody; + + int m_num_wheels_on_ground; + int m_indexRightAxis; + int m_indexUpAxis; + int m_indexForwardAxis; + + void defaultInit(const btVehicleTuning& tuning); + +public: + + //constructor to create a car from an existing rigidbody + btKart(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ); + + virtual ~btKart() ; + + + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step) + { + (void) collisionWorld; + updateVehicle(step); + } + + ///btActionInterface interface + void debugDraw(btIDebugDraw* debugDrawer); + + const btTransform& getChassisWorldTransform() const; + + btScalar rayCast(btWheelInfo& wheel); + + virtual void updateVehicle(btScalar step); + + + void resetSuspension(); + + btScalar getSteeringValue(int wheel) const; + + void setSteeringValue(btScalar steering,int wheel); + + + void applyEngineForce(btScalar force, int wheel); + + const btTransform& getWheelTransformWS( int wheelIndex ) const; + + void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true ); + +// void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth); + + btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel); + + inline int getNumWheels() const { + return int (m_wheelInfo.size()); + } + + btAlignedObjectArray m_wheelInfo; + + + const btWheelInfo& getWheelInfo(int index) const; + + btWheelInfo& getWheelInfo(int index); + + void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true); + + + void setBrake(btScalar brake,int wheelIndex); + + void setPitchControl(btScalar pitch) + { + m_pitchControl = pitch; + } + + void updateSuspension(btScalar deltaTime); + + virtual void updateFriction(btScalar timeStep); + + + + inline btRigidBody* getRigidBody() + { + return m_chassisBody; + } + + const btRigidBody* getRigidBody() const + { + return m_chassisBody; + } + + inline int getRightAxis() const + { + return m_indexRightAxis; + } + inline int getUpAxis() const + { + return m_indexUpAxis; + } + + inline int getForwardAxis() const + { + return m_indexForwardAxis; + } + + + ///Worldspace forward vector + btVector3 getForwardVector() const + { + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + return forwardW; + } + + ///Velocity of vehicle (positive if velocity vector has same direction as foward vector) + btScalar getCurrentSpeedKmHour() const + { + return m_currentVehicleSpeedKmHour; + } + + virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex) + { + m_indexRightAxis = rightIndex; + m_indexUpAxis = upIndex; + m_indexForwardAxis = forwardIndex; + } + + + ///backwards compatibility + int getUserConstraintType() const + { + return m_userConstraintType ; + } + + void setUserConstraintType(int userConstraintType) + { + m_userConstraintType = userConstraintType; + }; + + void setUserConstraintId(int uid) + { + m_userConstraintId = uid; + } + + int getUserConstraintId() const + { + return m_userConstraintId; + } +private: + btScalar rayCast(btWheelInfo& wheel, const btVector3& ray); +public: + void setSliding(bool active); + void activateZipper(float speed); + void deactivateZipper(); + bool btKart::projectVehicleToSurface(const btVector3& ray, + bool translate_vehicle); + // ------------------------------------------------------------------------ + /** Returns the number of wheels on the ground. */ + unsigned int getNumWheelsOnGround() const {return m_num_wheels_on_ground;} }; -#endif //BT_KART_H +#if 0 +class btDefaultVehicleRaycaster : public btVehicleRaycaster +{ + btDynamicsWorld* m_dynamicsWorld; +public: + btDefaultVehicleRaycaster(btDynamicsWorld* world) + :m_dynamicsWorld(world) + { + } + + virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result); + +}; +#endif + +#endif //BT_RAYCASTVEHICLE_H diff --git a/src/physics/btKartRaycast.hpp b/src/physics/btKartRaycast.hpp index dc6f3fdf4..b05420066 100644 --- a/src/physics/btKartRaycast.hpp +++ b/src/physics/btKartRaycast.hpp @@ -8,8 +8,8 @@ * of this software for any purpose. * It is provided "as is" without express or implied warranty. */ -#ifndef BTKARTRAYCASTER_HPP -#define BTKARTRAYCSATER_HPP +#ifndef BTKARTRAYCAST_HPP +#define BTKARTRAYCAST_HPP #include "BulletDynamics/Dynamics/btRigidBody.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" From b34fc058aa5fdaab1e55a3dad9c1e86f0e24b523 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 9 Nov 2011 04:49:53 +0000 Subject: [PATCH 03/68] 1) Added new physics properties to kart_properties to tune kart stability. 2) Made the kart accessible in btKart (so that the physics can access the kart properties directly). 3) Removed unused tuning variable in constructor of btKart. 4) Removed jumping related code. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10147 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/stk_config.xml | 37 ++++++++++++++--------------- src/config/stk_config.cpp | 1 + src/karts/kart.cpp | 24 +++++-------------- src/karts/kart.hpp | 4 +--- src/karts/kart_properties.cpp | 40 +++++++++++++++++-------------- src/karts/kart_properties.hpp | 44 +++++++++++++++++++++++++---------- src/physics/btKart.cpp | 16 ++++++------- src/physics/btKart.hpp | 11 +++++++-- 8 files changed, 97 insertions(+), 80 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index 2bd0dfd17..2e00e8d06 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -44,7 +44,7 @@ - + @@ -231,9 +231,12 @@ - + rest: Length of suspension when at rest. + travel-cm: maximum movement of suspension - in cm!! + exp-string-response: dampen the suspension spring reaction + exponentially --> + - + @@ -253,26 +256,22 @@ + impact of roll. + downward-impulse-factor: A speed proportional impulse applied each + frame that pushes the vehicle onto the ground. + track-connection-accel: An artificial force that pulls a wheel to + the ground if its off ground. Reduces the affect if a kart loses + contact with the ground (i.e. it then can't steer or accelerate + anymore). --> + chassis-angular-damping="0" + downward-impulse-factor="0.1" + track-connection-accel="2"/> - - - - - - - + @@ -266,7 +266,7 @@ diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 294506e6e..c06b8e75c 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -370,6 +370,12 @@ void btKart::updateVehicle( btScalar step ) wheel.m_deltaRotation *= btScalar(0.99); } + float f = -m_kart->getSpeed() + * m_kart->getKartProperties()->getDownwardImpulseFactor(); + btVector3 downwards_impulse = m_chassisBody->getWorldTransform().getBasis() + * btVector3(0, f, 0); + + m_chassisBody->applyCentralImpulse(downwards_impulse); } // updateVehicle // ---------------------------------------------------------------------------- From 158bf710464b8b343a5385e1f32589e5d3f19833 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 13 Nov 2011 20:53:23 +0000 Subject: [PATCH 10/68] Fixed include path. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10175 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/physics/btKart.hpp b/src/physics/btKart.hpp index d8bd07015..163157ce0 100644 --- a/src/physics/btKart.hpp +++ b/src/physics/btKart.hpp @@ -13,7 +13,7 @@ #include "BulletDynamics/Dynamics/btRigidBody.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" -#include "btkartRaycast.hpp" +#include "physics/btkartRaycast.hpp" class btDynamicsWorld; #include "LinearMath/btAlignedObjectArray.h" #include "BulletDynamics/Vehicle/btWheelInfo.h" From 587084e7125026f7d70d95c080f920a75082b898 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 13 Nov 2011 20:54:35 +0000 Subject: [PATCH 11/68] Updated documentation. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10176 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/race/history.cpp | 2 +- src/race/history.hpp | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/race/history.cpp b/src/race/history.cpp index 30287de5f..6dec01684 100644 --- a/src/race/history.cpp +++ b/src/race/history.cpp @@ -153,7 +153,7 @@ void History::updateReplay(float dt) */ void History::Save() { - FILE *fd = fopen("history.dat","w"); + FILE *fd = fopen("history.dat","w"); if(fd) printf("History saved in ./history.dat.\n"); else diff --git a/src/race/history.hpp b/src/race/history.hpp index b96249d4a..08057c6f9 100644 --- a/src/race/history.hpp +++ b/src/race/history.hpp @@ -47,18 +47,35 @@ public: HISTORY_POSITION = 1, HISTORY_PHYSICS = 2 }; private: - // maximum number of history events to store + /** maximum number of history events to store. */ HistoryReplayMode m_replay_mode; + + /** Points to the last used entry, and will wrap around. */ int m_current; + + /** True if the buffer has wrapped around. */ bool m_wrapped; + + /** Counts how many entries in the arrays are used. So if + * the buffer hasn't wrapped around, this will indicate + * how many entries to save. */ int m_size; + + /** Stores all time step sizes. */ std::vector m_all_deltas; + + /** Stores the kart controls being used (for physics replay). */ std::vector m_all_controls; + + /** Stores the coordinates (for simple replay). */ AlignedArray m_all_xyz; + + /** Stores the rotations of the karts. */ AlignedArray m_all_rotations; /** The identities of the karts to use. */ std::vector m_kart_ident; + void allocateMemory(int number_of_frames); void updateSaving(float dt); void updateReplay(float dt); @@ -70,7 +87,7 @@ public: void Save (); void Load (); - // ------------------------------------------------------------------------ + // -------------------I----------------------------------------------------- /** Returns the identifier of the n-th kart. */ const std::string& getKartIdent(unsigned int n) { From 79bb18870bd25ca2ce3e97e2c4d417a6c1a0eae3 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 13 Nov 2011 22:28:38 +0000 Subject: [PATCH 12/68] Fixed compilation problems, removed unused code. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10179 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.hpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/physics/btKart.hpp b/src/physics/btKart.hpp index 163157ce0..766ff6a95 100644 --- a/src/physics/btKart.hpp +++ b/src/physics/btKart.hpp @@ -13,7 +13,7 @@ #include "BulletDynamics/Dynamics/btRigidBody.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" -#include "physics/btkartRaycast.hpp" +#include "physics/btKartRaycast.hpp" class btDynamicsWorld; #include "LinearMath/btAlignedObjectArray.h" #include "BulletDynamics/Vehicle/btWheelInfo.h" @@ -228,27 +228,12 @@ public: void setSliding(bool active); void activateZipper(float speed); void deactivateZipper(); - bool btKart::projectVehicleToSurface(const btVector3& ray, - bool translate_vehicle); + bool projectVehicleToSurface(const btVector3& ray, + bool translate_vehicle); // ------------------------------------------------------------------------ /** Returns the number of wheels on the ground. */ unsigned int getNumWheelsOnGround() const {return m_num_wheels_on_ground;} }; -#if 0 -class btDefaultVehicleRaycaster : public btVehicleRaycaster -{ - btDynamicsWorld* m_dynamicsWorld; -public: - btDefaultVehicleRaycaster(btDynamicsWorld* world) - :m_dynamicsWorld(world) - { - } - - virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result); - -}; -#endif - #endif //BT_RAYCASTVEHICLE_H From 9901f983f3239c095bdbd953a07b0c96484c4d13 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 13 Nov 2011 23:36:21 +0000 Subject: [PATCH 13/68] Fixed typos in comments. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10190 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/stk_config.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index 8f2deccbc..270f7e688 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -49,15 +49,15 @@ - + + time for skidmarks to fade out. --> + disabled when the kart is more than this value from the track. --> From d2d8ec970d77bdf1c437f9fc6c6489e9d8e3417a Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 13 Nov 2011 23:59:37 +0000 Subject: [PATCH 14/68] Fixed outdated explosion documentation. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10197 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/stk_config.xml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index 270f7e688..4491c0a0f 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -290,11 +290,13 @@ band-speed-increase="7" band-fade-out-time="3" in-face-time="4 6 7"/> - + after being hit by an explosion. + radius: Kart closer to this value will be affected by + an explosion as well. --> From 311fef872636b7c7c8aac3bbc1583b198c18a67e Mon Sep 17 00:00:00 2001 From: hikerstk Date: Mon, 14 Nov 2011 06:04:32 +0000 Subject: [PATCH 15/68] Replaying now loops back to the beginning of the recording. Note that atm the physics values of karts (speed, suspension etc) are not reset, which can cause difference when looping. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10201 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/race/history.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/race/history.cpp b/src/race/history.cpp index 6dec01684..ff9195bfd 100644 --- a/src/race/history.cpp +++ b/src/race/history.cpp @@ -124,12 +124,18 @@ void History::updateSaving(float dt) void History::updateReplay(float dt) { m_current++; + World *world = World::getWorld(); if(m_current>=(int)m_all_deltas.size()) { printf("Replay finished.\n"); - exit(2); + m_current = 0; + // Note that for physics replay all physics parameters + // need to be reset, e.g. velocity, ... + for(unsigned int i=0; igetNumKarts(); i++) + { + world->getKart(i)->reset(); + } } - World *world = World::getWorld(); unsigned int num_karts = world->getNumKarts(); for(unsigned k=0; k Date: Mon, 14 Nov 2011 06:05:27 +0000 Subject: [PATCH 16/68] Bugfix: physics replay didn't work (due to incorrect sscanf format). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10202 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/race/history.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/race/history.cpp b/src/race/history.cpp index ff9195bfd..793d27866 100644 --- a/src/race/history.cpp +++ b/src/race/history.cpp @@ -345,8 +345,7 @@ void History::Load() fgets(s, 1023, fd); int buttonsCompressed; float x,y,z,rx,ry,rz,rw; - sscanf(s, "%d %f %f %d %f %f %f %f %f %f %f\n", - &j, + sscanf(s, "%f %f %d %f %f %f %f %f %f %f\n", &m_all_controls[i].m_steer, &m_all_controls[i].m_accel, &buttonsCompressed, From 09d998bc2441d496d905bd4fe2821f7f3e0a7db6 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Mon, 14 Nov 2011 11:56:14 +0000 Subject: [PATCH 17/68] Only save history when the key is pressed (and not again when it is released). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10203 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/input/input_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index 9097aae76..60d170352 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -235,7 +235,7 @@ void InputManager::handleStaticAction(int key, int value) break; case KEY_F10: - if(world) history->Save(); + if(world && value) history->Save(); break; case KEY_F11: From c537c6873e0b4d09343e2079e67427a52b41b489 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Mon, 14 Nov 2011 11:57:11 +0000 Subject: [PATCH 18/68] Reset history data each time a race is started (to avoid that previous history data is used). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10204 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/modes/world.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 6a7f29af1..c4e63fc0c 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -902,6 +902,9 @@ void World::restartRace() projectile_manager->cleanup(); race_manager->reset(); + // Make sure to overwrite the data from the previous race. + if(!history->replayHistory()) history->initRecording(); + } // restartRace //----------------------------------------------------------------------------- From 6ece9c562491357a6cf761feb984bb5292547870 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 15 Nov 2011 12:05:41 +0000 Subject: [PATCH 19/68] Removed unnecessary #include, sorted class declaration, added & to getResetTransform. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10217 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/kart.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 8e1492c2f..31cb0e39b 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -27,7 +27,7 @@ * of karts. */ -#include "btBulletDynamicsCommon.h" +#include "LinearMath/btTransform.h" #include "items/attachment.hpp" #include "items/powerup.hpp" @@ -36,24 +36,23 @@ #include "karts/emergency_animation.hpp" #include "karts/max_speed.hpp" #include "karts/moveable.hpp" -#include "karts/kart_model.hpp" #include "karts/kart_properties.hpp" -//#include "physics/btKart.hpp" #include "tracks/terrain_info.hpp" #include "utils/no_copy.hpp" class btKart; class btUprightConstraint; + class Camera; class Item; -class Quad; -class Shadow; -class SFXBase; -class SkidMarks; -class SlipStream; +class KartModel; class ParticleEmitter; class ParticleKind; class Rain; +class SFXBase; +class Shadow; +class SkidMarks; +class SlipStream; /** The main kart class. All type of karts are of this object, but with * different controllers. The controllers are what turn a kart into a @@ -414,7 +413,7 @@ public: const std::string& getIdent() const {return m_kart_properties->getIdent();} // ------------------------------------------------------------------------ /** Returns the start transform, i.e. position and rotation. */ - const btTransform getResetTransform() const {return m_reset_transform;} + const btTransform& getResetTransform() const {return m_reset_transform;} // ------------------------------------------------------------------------ /** Returns the controller of this kart. */ Controller* getController() { return m_controller; } From e37c2256542b8f940777f53ecd0acc702f65f742 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 16 Nov 2011 01:37:08 +0000 Subject: [PATCH 20/68] Reset the 'reminder' time maintained by bullet (which uses fixed time steps), so that in physics replay the time steps are now correct. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10219 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- CMakeLists.txt | 1 + src/Makefile.am | 1 + src/ide/vc9/supertuxkart.vcproj | 44 +++++++++++++++------------- src/modes/world.cpp | 4 +++ src/physics/physics.cpp | 9 +++--- src/physics/physics.hpp | 11 +++++-- src/physics/stk_dynamics_world.hpp | 47 ++++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 27 deletions(-) create mode 100644 src/physics/stk_dynamics_world.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5eb7cd130..f7e2c248a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -466,6 +466,7 @@ set( SRCS ${SRCS} src/main.cpp src/physics/physical_object.hpp src/physics/physics.cpp src/physics/physics.hpp + src/physics/stk_dynamics_world.hpp src/physics/triangle_mesh.cpp src/physics/triangle_mesh.hpp src/physics/user_pointer.hpp diff --git a/src/Makefile.am b/src/Makefile.am index b04fb4d9c..8b2cf41a9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -289,6 +289,7 @@ supertuxkart_SOURCES = \ physics/physical_object.hpp \ physics/physics.cpp \ physics/physics.hpp \ + phsyics/stk_dynamics_world.hpp \ physics/triangle_mesh.cpp \ physics/triangle_mesh.hpp \ physics/user_pointer.hpp \ diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj index 3897cc53c..f07be912f 100644 --- a/src/ide/vc9/supertuxkart.vcproj +++ b/src/ide/vc9/supertuxkart.vcproj @@ -414,6 +414,26 @@ > + + + + + + + + + + - - - - - - - - - - @@ -1704,6 +1704,10 @@ RelativePath="..\..\physics\physics.hpp" > + + diff --git a/src/modes/world.cpp b/src/modes/world.cpp index c4e63fc0c..0e6f88f4f 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -368,6 +368,10 @@ void World::terminateRace() */ void World::resetAllKarts() { + // Reset the physics 'remaining' time to 0 so that the number + // of timesteps is reproducible if doing a physics-based history run + getPhysics()->getPhysicsWorld()->resetLocalTime(); + // If track checking is requested, check all rescue positions if // they are heigh enough. if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES && diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 5c4d4cf2c..6681df49a 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -27,6 +27,7 @@ #include "physics/btUprightConstraint.hpp" #include "physics/irr_debug_drawer.hpp" #include "physics/physical_object.hpp" +#include "physics/stk_dynamics_world.hpp" #include "physics/triangle_mesh.hpp" #include "tracks/track.hpp" @@ -48,10 +49,10 @@ Physics::Physics() : btSequentialImpulseConstraintSolver() void Physics::init(const Vec3 &world_min, const Vec3 &world_max) { m_axis_sweep = new btAxisSweep3(world_min, world_max); - m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher, - m_axis_sweep, - this, - m_collision_conf); + m_dynamics_world = new STKDynamicsWorld(m_dispatcher, + m_axis_sweep, + this, + m_collision_conf); m_dynamics_world->setGravity(btVector3(0.0f, -World::getWorld()->getTrack()->getGravity(), 0.0f)); diff --git a/src/physics/physics.hpp b/src/physics/physics.hpp index bde791fd0..9739cba20 100644 --- a/src/physics/physics.hpp +++ b/src/physics/physics.hpp @@ -31,10 +31,12 @@ #include "btBulletDynamicsCommon.h" #include "physics/irr_debug_drawer.hpp" +#include "physics/stk_dynamics_world.hpp" #include "physics/user_pointer.hpp" -class Vec3; class Kart; +class STKDynamicsWorld; +class Vec3; /** * \ingroup physics @@ -89,7 +91,10 @@ private: } }; // CollisionList - btDynamicsWorld *m_dynamics_world; + /** Pointer to the physics dynamics world. */ + STKDynamicsWorld *m_dynamics_world; + + /** Used in physics debugging to draw the physics world. */ IrrDebugDrawer *m_debug_drawer; btCollisionDispatcher *m_dispatcher; btBroadphaseInterface *m_axis_sweep; @@ -107,7 +112,7 @@ public: void KartKartCollision(Kart *ka, Kart *kb); void update (float dt); void draw (); - btDynamicsWorld* + STKDynamicsWorld* getPhysicsWorld () const {return m_dynamics_world;} /** Activates the next debug mode (or switches it off again). */ diff --git a/src/physics/stk_dynamics_world.hpp b/src/physics/stk_dynamics_world.hpp new file mode 100644 index 000000000..3d5d7b677 --- /dev/null +++ b/src/physics/stk_dynamics_world.hpp @@ -0,0 +1,47 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011 Joerg Henrichs +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_STK_DYNAMICS_WORLD_HPP +#define HEADER_STK_DYNAMICS_WORLD_HPP + +#include "btBulletDynamicsCommon.h" + +class STKDynamicsWorld : public btDiscreteDynamicsWorld +{ +public: + /** The standard constructor which just created a btDiscreteDynamicsWorld. */ + STKDynamicsWorld(btDispatcher* dispatcher, + btBroadphaseInterface* pairCache, + btConstraintSolver* constraintSolver, + btCollisionConfiguration* collisionConfiguration) + + : btDiscreteDynamicsWorld(dispatcher, pairCache, + constraintSolver, + collisionConfiguration) + { + } + + /** Resets m_localTime to 0. This allows more precise replay of + * physics, which is important for replaying histories. */ + virtual void resetLocalTime() { m_localTime = 0; } + +}; // STKDynamicsWorld +#endif +/* EOF */ + From d1e132fbcbaff2a15ee3a8965b44e1645960a0af Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 16 Nov 2011 21:15:25 +0000 Subject: [PATCH 21/68] Fixed physical history replay, it appears to be bitwise identical now (#498). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10220 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/kart.cpp | 6 +++++- src/physics/btKart.cpp | 15 +++++++++++++++ src/physics/btKart.hpp | 1 + src/race/history.cpp | 6 ++---- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index dc04d38fe..b3337b88d 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -537,6 +537,7 @@ void Kart::reset() m_bounce_back_time = 0.0f; m_skidding = 1.0f; m_time_last_crash = 0.0f; + m_speed = 0.0f; m_view_blocked_by_plunger = 0.0f; if(m_terrain_sound) @@ -575,9 +576,12 @@ void Kart::reset() if (m_skidmarks) { m_skidmarks->reset(); - m_skidmarks->adjustFog( track_manager->getTrack( race_manager->getTrackName() )->isFogEnabled() ); + const Track *track = + track_manager->getTrack( race_manager->getTrackName() ); + m_skidmarks->adjustFog(track->isFogEnabled() ); } + m_vehicle->reset(); for(int j=0; jgetNumWheels(); j++) { m_vehicle->updateWheelTransform(j, true); diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index c06b8e75c..5ffc2f7db 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -95,6 +95,21 @@ btWheelInfo& btKart::addWheel(const btVector3& connectionPointCS, return wheel; } // addWheel +// ---------------------------------------------------------------------------- +/** Resets the kart before a (re)start, to make sure all physics variable + * are properly defined. This is especially important for physics replay. + */ +void btKart::reset() +{ + for(int i=0; igetNumKarts(); i++) - { - world->getKart(i)->reset(); - } + world->restartRace(); } unsigned int num_karts = world->getNumKarts(); for(unsigned k=0; k Date: Tue, 22 Nov 2011 23:15:27 +0000 Subject: [PATCH 22/68] Make the physics branch compile with current irrlicht svn. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10241 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/guiengine/widgets/CGUIEditBox.cpp | 2 +- src/guiengine/widgets/CGUIEditBox.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guiengine/widgets/CGUIEditBox.cpp b/src/guiengine/widgets/CGUIEditBox.cpp index c1baf72c4..bc67a3df6 100644 --- a/src/guiengine/widgets/CGUIEditBox.cpp +++ b/src/guiengine/widgets/CGUIEditBox.cpp @@ -115,7 +115,7 @@ void CGUIEditBox::setOverrideColor(video::SColor color) } -video::SColor const& CGUIEditBox::getOverrideColor() const +video::SColor CGUIEditBox::getOverrideColor() const { return OverrideColor; } diff --git a/src/guiengine/widgets/CGUIEditBox.h b/src/guiengine/widgets/CGUIEditBox.h index a95cf3408..b0031dffb 100644 --- a/src/guiengine/widgets/CGUIEditBox.h +++ b/src/guiengine/widgets/CGUIEditBox.h @@ -36,7 +36,7 @@ using namespace gui; virtual void setOverrideColor(video::SColor color); //! Gets the override color - virtual video::SColor const & getOverrideColor() const; + virtual video::SColor getOverrideColor() const; //! Sets if the text should use the overide color or the //! color in the gui skin. From f0bf730a9db54aafe608ca17d1c56222975b69e7 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 22 Nov 2011 23:16:19 +0000 Subject: [PATCH 23/68] Removed compiler warning. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10242 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/kart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index b3337b88d..ae6ae9a6a 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -755,7 +755,7 @@ float Kart::getActualWheelForce() */ bool Kart::isOnGround() const { - return (m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels() + return ((int)m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels() && !playingEmergencyAnimation()); } // isOnGround From 06a96ed35673f2d2bf40adbfec47b4301b033fde Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 23 Nov 2011 20:52:43 +0000 Subject: [PATCH 24/68] Accept heading angle in degree instead of radians, which is easier (considering that the special start-tag is mostly used when manually debugging). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10247 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/track.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 3925dcdb5..56b5fe3fb 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1233,7 +1233,8 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id) m_start_transforms[position].setOrigin(xyz); m_start_transforms[position].setRotation( - btQuaternion(btVector3(0,1,0),h ) ); + btQuaternion(btVector3(0,1,0), + h*DEGREE_TO_RAD ) ); } else if(name=="camera") { From 0c5125522daff4e189f30386a55e36e1569d764b Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 24 Nov 2011 09:49:30 +0000 Subject: [PATCH 25/68] Fixed --log=file/terminal (the stdout/err files were opened before the command line flag was tested, so the behaviour depended on the setting in the previous runs, which were saved). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10249 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/main.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b560cba02..5c6042372 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -456,6 +456,15 @@ int handleCmdLinePreliminary(int argc, char **argv) { UserConfigParams::m_verbosity |= UserConfigParams::LOG_MISC; } + else if( !strcmp(argv[i], "--log=terminal")) + { + UserConfigParams::m_log_errors=false; + } + else if( !strcmp(argv[i], "--log=file")) + { + UserConfigParams::m_log_errors=true; + } + else if ( !strcmp(argv[i], "--debug=all") ) { UserConfigParams::m_verbosity |= UserConfigParams::LOG_ALL; @@ -863,14 +872,7 @@ int handleCmdLine(int argc, char **argv) race_manager->setNumLaps(atoi(argv[i+1])); i++; } - else if( !strcmp(argv[i], "--log=terminal")) - { - UserConfigParams::m_log_errors=false; - } - else if( !strcmp(argv[i], "--log=file")) - { - UserConfigParams::m_log_errors=true; - } else if( sscanf(argv[i], "--profile-laps=%d", &n)==1) + else if( sscanf(argv[i], "--profile-laps=%d", &n)==1) { printf("Profiling %d laps\n",n); UserConfigParams::m_no_start_screen = true; @@ -927,6 +929,8 @@ int handleCmdLine(int argc, char **argv) else if( !strcmp(argv[i], "--debug=flyable") ) {} else if( !strcmp(argv[i], "--debug=misc" ) ) {} else if( !strcmp(argv[i], "--debug=all" ) ) {} + else if( !strcmp(argv[i], "--log=terminal" ) ) {} + else if( !strcmp(argv[i], "--log=file" ) ) {} else if( !strcmp(argv[i], "--screensize") || !strcmp(argv[i], "-s") ) {i++;} else if( !strcmp(argv[i], "--fullscreen") || !strcmp(argv[i], "-f")) {} From fd1871be6e0b0f628020fd969f96f8a5784cf69c Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 24 Nov 2011 10:13:37 +0000 Subject: [PATCH 26/68] Bugfix: adding the radius to the raycast length was lost in the branch. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10250 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 5ffc2f7db..e53c7bb6d 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -201,7 +201,8 @@ btScalar btKart::rayCast(btWheelInfo& wheel) btScalar depth = -1; - btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius; + btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius + + wheel.m_maxSuspensionTravelCm*0.01f; btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; From 78505d2a8b7db9fc5e8b9fd67d2a79223c0596c1 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 24 Nov 2011 10:20:12 +0000 Subject: [PATCH 27/68] Added lost improvement: make sure that both wheels of an axis are touching the ground if at least one wheel touches it (if only one wheel touches the ground, the kart will get a strong angular impulse and turn rapidly). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10251 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index e53c7bb6d..2266d2d99 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -326,6 +326,30 @@ void btKart::updateVehicle( btScalar step ) if(m_wheelInfo[i].m_raycastInfo.m_isInContact) m_num_wheels_on_ground++; } + // Work around: make sure that either both wheels on one axis + // are on ground, or none of them. This avoids the problem of + // the kart suddenly getting additional angular velocity because + // e.g. only one rear wheel is on the ground. + for(i=0; i Date: Thu, 24 Nov 2011 10:26:27 +0000 Subject: [PATCH 28/68] Re-added support for track connection acceleration (for backward compatibility). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10252 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 2266d2d99..3a5ae5a3f 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -478,7 +478,15 @@ void btKart::updateSuspension(btScalar deltaTime) btWheelInfo &wheel_info = m_wheelInfo[w_it]; if ( !wheel_info.m_raycastInfo.m_isInContact ) { - wheel_info.m_wheelsSuspensionForce = btScalar(0.0); + // A very unphysical thing to handle slopes that are a bit too + // steep or uneven (resulting in only one wheel on the ground) + // If only the front or only the rear wheels are on the ground, add + // a force pulling the axis down (towards the ground). Note that it + // is already guaranteed that either both or no wheels on one axis + // are on the ground, so we have to test only one of the wheels + wheel_info.m_wheelsSuspensionForce = + -m_kart->getKartProperties()->getTrackConnectionAccel() + * chassisMass; continue; } From 88909254707e920ee771f421d911cb60b514703f Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 24 Nov 2011 10:29:14 +0000 Subject: [PATCH 29/68] Adding braking improvement back in. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10253 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 3a5ae5a3f..ee55c6602 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -678,6 +678,14 @@ void btKart::updateFriction(btScalar timeStep) wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel],maxImpulse); rollingFriction = calcRollingFriction(contactPt); + // This is a work around for the problem that a kart shakes + // if it is braking: we get a minor impulse forward, which + // bullet then tries to offset by applying a backward + // impulse - which is a bit too big, causing a impulse + // backwards, ... till the kart is shaking backwards and + // forwards + if(wheelInfo.m_brake && fabsf(rollingFriction)<10) + rollingFriction=0; } //switch between active rolling (throttle), braking and non-active From ac90c43f72aaf68bb62a155067f2f1a472a81e85 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 24 Nov 2011 21:42:54 +0000 Subject: [PATCH 30/68] Restore the original settings while trying to get the old and new physics to behave identical when all new features are switched off. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10256 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/stk_config.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index 4491c0a0f..5034b88d4 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -208,7 +208,7 @@ the wheel can go from -1 to +1 steering in one frame, basically disabling this mechanism. --> - + - + @@ -267,7 +267,7 @@ chassis-linear-damping="0.2" chassis-angular-damping="0" downward-impulse-factor="2" - track-connection-accel="2"/> + track-connection-accel="0"/> From d4564dd40d0da9ebc4cb11378842356975fa702f Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 30 Nov 2011 08:26:59 +0000 Subject: [PATCH 31/68] Re-introduced a fix for (apparently) hexley, not sure if this should be kept, but for backwards compatibility added it back with an #ifdef. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10278 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index ee55c6602..10e7672f8 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -738,7 +738,13 @@ void btKart::updateFriction(btScalar timeStep) { m_chassisBody->applyImpulse( m_forwardWS[wheel]*(m_forwardImpulse[wheel]), +#define COMPATIBLE_0_7_3 +#ifdef COMPATIBLE_0_7_3 + // This was apparently done to help hexley + btVector3(0,0,0)); +#else rel_pos); +#endif } if (m_sideImpulse[wheel] != btScalar(0.)) { From d7d8d4aa6ce5f1fbb5e8a70bd12576a30219a9dc Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 30 Nov 2011 11:33:27 +0000 Subject: [PATCH 32/68] Applied missing patch from trunk that applies the force only sideways. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10280 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 10e7672f8..d4c8f0215 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -752,6 +752,15 @@ void btKart::updateFriction(btScalar timeStep) (btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - groundObject->getCenterOfMassPosition(); + //adjust relative position above ground so that force only + // acts sideways + btVector3 delta_vec = (wheelInfo.m_raycastInfo.m_hardPointWS + - wheelInfo.m_raycastInfo.m_contactPointWS); + if (delta_vec.length() != btScalar (0)) + { + delta_vec = delta_vec.normalize(); + rel_pos -= delta_vec * rel_pos.dot(delta_vec); + } btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; From 31aed84b82f9fffe3d39da27d73cbbed53bf1306 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 30 Nov 2011 11:36:38 +0000 Subject: [PATCH 33/68] Disabled a bug fix from bullet 2.79 if backwards compatibility (to stk 0.7.3) is used. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10281 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index d4c8f0215..d0b5d62b7 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -764,7 +764,7 @@ void btKart::updateFriction(btScalar timeStep) btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; -#if defined ROLLING_INFLUENCE_FIX +#if defined ROLLING_INFLUENCE_FIX && !defined COMPATIBLE_0_7_3 // fix. It only worked if car's up was along Y - VT. btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform() From 4dbdc5c588eaa0cd66b7b878777986762487b820 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 30 Nov 2011 23:33:00 +0000 Subject: [PATCH 34/68] (Re-)Added support for disablind sliding and zipper (based on implementation in trunk). Now the physics branch (with disabled new features) behaves like current trunk. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10287 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/physics/btKart.cpp | 45 +++++++++++++++++++++++++++++++++++------- src/physics/btKart.hpp | 24 +++++++++++----------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index d0b5d62b7..03974c356 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -38,17 +38,14 @@ btRigidBody& btActionInterface::getFixedBody() // ============================================================================ btKart::btKart(btRigidBody* chassis, btVehicleRaycaster* raycaster, Kart *kart) - : m_vehicleRaycaster(raycaster), - m_pitchControl(btScalar(0.)) + : m_vehicleRaycaster(raycaster) { m_chassisBody = chassis; m_indexRightAxis = 0; m_indexUpAxis = 2; m_indexForwardAxis = 1; - m_currentVehicleSpeedKmHour = btScalar(0.); - m_steeringValue = btScalar(0.); - m_num_wheels_on_ground = 0; m_kart = kart; + reset(); } // btKart // ---------------------------------------------------------------------------- @@ -108,6 +105,11 @@ void btKart::reset() wheel.m_rotation = 0; updateWheelTransformsWS(wheel); } + m_zipper_active = false; + m_zipper_velocity = btScalar(0); + m_allow_sliding = false; + m_currentVehicleSpeedKmHour = btScalar(0.); + m_num_wheels_on_ground = 0; } // reset // ---------------------------------------------------------------------------- @@ -662,6 +664,21 @@ void btKart::updateFriction(btScalar timeStep) (btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; if(!groundObject) continue; + if(m_zipper_active && m_zipper_velocity > 0) + { + if (wheel==2 || wheel==3) + { + // The zipper velocity is the speed that should be + // reached. So compute the impulse to accelerate the + // kart up to that speed: + m_forwardImpulse[wheel] = + 0.5f*(m_zipper_velocity - + getRigidBody()->getLinearVelocity().length()) + / m_chassisBody->getInvMass(); + } + + } + btScalar rollingFriction = 0.f; if (wheelInfo.m_engineForce != 0.f) @@ -713,12 +730,15 @@ void btKart::updateFriction(btScalar timeStep) } // for (int wheel=0; wheel m_forwardWS; btAlignedObjectArray m_axle; btAlignedObjectArray m_forwardImpulse; @@ -59,12 +59,17 @@ public: }; protected: - btScalar m_tau; - btScalar m_damping; - btVehicleRaycaster* m_vehicleRaycaster; - btScalar m_pitchControl; - btScalar m_steeringValue; - btScalar m_currentVehicleSpeedKmHour; + btScalar m_damping; + btVehicleRaycaster *m_vehicleRaycaster; + btScalar m_currentVehicleSpeedKmHour; + bool m_zipper_active; + btScalar m_zipper_velocity; + + /** Sliding (skidding) will only be permited when this is true. Also check + * the friction parameter in the wheels since friction directly affects + * skidding. + */ + bool m_allow_sliding; btRigidBody* m_chassisBody; @@ -139,11 +144,6 @@ public: void setBrake(btScalar brake,int wheelIndex); - - void setPitchControl(btScalar pitch) - { - m_pitchControl = pitch; - } void updateSuspension(btScalar deltaTime); From 943128e528961eb28a5e25ceb56936b624597d88 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 30 Nov 2011 23:36:42 +0000 Subject: [PATCH 35/68] Disabled downward impulse as default. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/physics@10288 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/stk_config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index 5034b88d4..00b6067e3 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -266,7 +266,7 @@ From d81cc54fa895706e9269008bfcc248620fefb3fd Mon Sep 17 00:00:00 2001 From: mcmic Date: Fri, 3 Feb 2012 23:18:14 +0000 Subject: [PATCH 37/68] Implementation of reversed track. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10799 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/quad.cpp | 11 +++++++++++ src/tracks/quad.hpp | 3 +++ src/tracks/quad_graph.cpp | 25 ++++++++++++++++++++----- src/tracks/quad_graph.hpp | 4 ++++ src/tracks/quad_set.cpp | 7 +++++++ src/tracks/quad_set.hpp | 1 + 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/tracks/quad.cpp b/src/tracks/quad.cpp index 8a62bceb6..3f9dc24ce 100644 --- a/src/tracks/quad.cpp +++ b/src/tracks/quad.cpp @@ -131,3 +131,14 @@ void Quad::transform(const btTransform &t, Quad *result) const std::min(result->m_p[2].getY(), result->m_p[3].getY()) ); } // transform + +// ---------------------------------------------------------------------------- +/** Reverse the quad */ +void Quad::reverse() { + Vec3 tmp = m_p[0]; + m_p[0] = m_p[2]; + m_p[2] = tmp; + tmp = m_p[1]; + m_p[1] = m_p[3]; + m_p[3] = tmp; +} diff --git a/src/tracks/quad.hpp b/src/tracks/quad.hpp index fb123f407..47566ded9 100644 --- a/src/tracks/quad.hpp +++ b/src/tracks/quad.hpp @@ -75,5 +75,8 @@ public: // ------------------------------------------------------------------------ /** True if this quad should be ignored by the AI. */ bool letAIIgnore() const { return m_ai_ignore; } + + /** Reverse the quad */ + void reverse(); }; // class Quad #endif diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index a78d4dbdb..519fa3e57 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -44,13 +44,16 @@ QuadGraph *QuadGraph::m_quad_graph = NULL; */ QuadGraph::QuadGraph(const std::string &quad_file_name, const std::string graph_file_name, - const bool reverse) + const bool reverse) : m_reverse(reverse) { m_node = NULL; m_mesh = NULL; m_mesh_buffer = NULL; m_lap_length = 0; m_all_quads = new QuadSet(quad_file_name); + if(m_reverse) { + m_all_quads->reverse_all_quads(); + } m_quad_filename = quad_file_name; GraphNode::m_all_quads = m_all_quads; GraphNode::m_all_nodes = this; @@ -70,6 +73,14 @@ QuadGraph::~QuadGraph() } // ~QuadGraph // ----------------------------------------------------------------------------- + +void QuadGraph::addSuccessor(unsigned int from, unsigned int to) { + if(m_reverse) + m_all_nodes[to]->addSuccessor(from); + else + m_all_nodes[from]->addSuccessor(to); +} + /** Loads a quad graph from a file. * \param filename Name of the file to load. */ @@ -138,7 +149,8 @@ void QuadGraph::load(const std::string &filename) for(unsigned int i=from; i<=to; i++) { assert(i!=to ? i+1 : from addSuccessor(i!=to ? i+1 : from); + addSuccessor(i,(i!=to ? i+1 : from)); + //~ m_all_nodes[i]->addSuccessor(i!=to ? i+1 : from); } } else if(xml_node->getName()=="edge-line") @@ -149,7 +161,8 @@ void QuadGraph::load(const std::string &filename) xml_node->get("to", &to); for(unsigned int i=from; iaddSuccessor(i+1); + addSuccessor(i,i+1); + //~ m_all_nodes[i]->addSuccessor(i+1); } } else if(xml_node->getName()=="edge") @@ -159,7 +172,8 @@ void QuadGraph::load(const std::string &filename) xml_node->get("from", &from); xml_node->get("to", &to); assert(toaddSuccessor(to); + addSuccessor(from,to); + //~ m_all_nodes[from]->addSuccessor(to); } // edge else { @@ -281,7 +295,8 @@ void QuadGraph::setDefaultSuccessors() { for(unsigned int i=0; igetNumberOfSuccessors()==0) { - m_all_nodes[i]->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1); + addSuccessor(i,i+1>=m_all_nodes.size() ? 0 : i+1); + //~ m_all_nodes[i]->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1); } // if size==0 } // for i +#include #include "io/file_manager.hpp" #include "io/xml_node.hpp" @@ -44,6 +45,12 @@ QuadSet::~QuadSet() } // ~QuadSet // ----------------------------------------------------------------------------- +void reverse_quad(Quad* q) { + q->reverse(); +} +void QuadSet::reverse_all_quads() { + for_each(m_all_quads.begin(),m_all_quads.end(),reverse_quad); +} /** This function interprets a point specification as an attribute in the xml quadset file. It understands two different specifications: p1="n:p" : get point p from square n (n, p integers) diff --git a/src/tracks/quad_set.hpp b/src/tracks/quad_set.hpp index 39a897015..2d2006b26 100644 --- a/src/tracks/quad_set.hpp +++ b/src/tracks/quad_set.hpp @@ -47,6 +47,7 @@ public: QuadSet (const std::string& filename); ~QuadSet (); + void reverse_all_quads(); int getCurrentQuad(const Vec3& p, int oldQuad) const; const Quad& getQuad(int n) const {return *(m_all_quads[n]); } From 29192e7fc6b19c90b4d79b4aefb2f21c1ff9c72d Mon Sep 17 00:00:00 2001 From: mcmic Date: Sat, 4 Feb 2012 16:02:02 +0000 Subject: [PATCH 38/68] Added text next to reverse checkbox git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10800 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/states_screens/dialogs/track_info_dialog.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/states_screens/dialogs/track_info_dialog.cpp b/src/states_screens/dialogs/track_info_dialog.cpp index 52d0ab000..f3ee97689 100644 --- a/src/states_screens/dialogs/track_info_dialog.cpp +++ b/src/states_screens/dialogs/track_info_dialog.cpp @@ -135,7 +135,7 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin //I18N: In the track setup screen (number of laps choice, where %i is the number) m_spinner->setText( _("%i laps") ); - //~ m_widgets.push_back(m_spinner); + m_widgets.push_back(m_spinner); m_spinner->add(); m_spinner->setValue( UserConfigParams::m_num_laps ); m_spinner->getIrrlichtElement()->setTabStop(true); @@ -158,12 +158,20 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin m_checkbox->setParent(m_irrlicht_window); m_checkbox->m_properties[PROP_ID] = "reversecheckbox"; m_checkbox->m_properties[PROP_WARP_AROUND] = "true"; - m_checkbox->setText( _("Reverse track") ); + //~ m_checkbox->setText( _("Reverse track") ); m_widgets.push_back(m_checkbox); m_checkbox->add(); m_checkbox->setState(false); m_checkbox->getIrrlichtElement()->setTabStop(true); m_checkbox->getIrrlichtElement()->setTabGroup(false); + stringw text_reverse = _("Reverse"); + + IGUIStaticText* b = GUIEngine::getGUIEnv()->addStaticText( + text_reverse.c_str(), + core::rect< s32 >(m_checkbox->m_x+m_checkbox->m_w, m_checkbox->m_y+10, m_checkbox->m_x+200, m_checkbox->m_y+m_checkbox->m_h), + false , true , // border, word warp + m_irrlicht_window); + b->setTabStop(false); } else { From c49226aefcc0c05062a9a42de63705c2146b0279 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 5 Feb 2012 11:33:19 +0000 Subject: [PATCH 40/68] Fixed compiler warning. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10806 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/states_screens/dialogs/track_info_dialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/states_screens/dialogs/track_info_dialog.cpp b/src/states_screens/dialogs/track_info_dialog.cpp index f3ee97689..2de5c556c 100644 --- a/src/states_screens/dialogs/track_info_dialog.cpp +++ b/src/states_screens/dialogs/track_info_dialog.cpp @@ -152,7 +152,7 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin { m_checkbox = new CheckBoxWidget(); m_checkbox->m_x = m_area.getWidth()/2 - 400; - m_checkbox->m_y = (y2+y3)/2.0; + m_checkbox->m_y = (y2+y3)/2; m_checkbox->m_w = 60; m_checkbox->m_h = 60; m_checkbox->setParent(m_irrlicht_window); From 648eb17e0a1efc7d1842662c9fe5f3c03e904b31 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 5 Feb 2012 20:56:45 +0000 Subject: [PATCH 41/68] Added command line option for reversing tracks. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10808 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/main.cpp | 5 +++++ src/race/race_manager.cpp | 3 +-- src/race/race_manager.hpp | 4 +--- src/states_screens/dialogs/track_info_dialog.cpp | 15 ++++++++++----- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d4d892d82..2f9ceead0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -361,6 +361,7 @@ void cmdLineHelp (char* invocation) " --list-karts Show available karts.\n" " --laps N Define number of laps to N.\n" " --mode N N=1 novice, N=2 driver, N=3 racer.\n" + " --reverse Play track in reverse (if allowed)\n" // TODO: add back "--players" switch // " --players n Define number of players to between 1 and 4.\n" " --item STYLE Use STYLE as your item style.\n" @@ -766,6 +767,10 @@ int handleCmdLine(int argc, char **argv) } i++; } + else if( !strcmp(argv[i], "--reverse")) + { + race_manager->setReverseTrack(true); + } else if( (!strcmp(argv[i], "--track") || !strcmp(argv[i], "-t")) && i+1enterGameState(); setTrack(trackIdent.c_str()); if (num_laps != -1) setNumLaps( num_laps ); - setReverseTrack(reverse_track); setMajorMode(RaceManager::MAJOR_MODE_SINGLE); diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index 285fa3cac..374caf57f 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -496,10 +496,8 @@ public: * \param trackIdent Internal name of the track to race on * \param num_laps Number of laps to race, or -1 if number of laps is * not relevant in current mode - * \param reverse_track True if the track should be driven reverse */ - void startSingleRace(const std::string trackIdent, const int num_laps, - const bool reverse_track); + void startSingleRace(const std::string trackIdent, const int num_laps); /** \} */ diff --git a/src/states_screens/dialogs/track_info_dialog.cpp b/src/states_screens/dialogs/track_info_dialog.cpp index 2de5c556c..ff68b4fb7 100644 --- a/src/states_screens/dialogs/track_info_dialog.cpp +++ b/src/states_screens/dialogs/track_info_dialog.cpp @@ -168,7 +168,9 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin IGUIStaticText* b = GUIEngine::getGUIEnv()->addStaticText( text_reverse.c_str(), - core::rect< s32 >(m_checkbox->m_x+m_checkbox->m_w, m_checkbox->m_y+10, m_checkbox->m_x+200, m_checkbox->m_y+m_checkbox->m_h), + core::rect< s32 >(m_checkbox->m_x+m_checkbox->m_w, + m_checkbox->m_y+10, m_checkbox->m_x+200, + m_checkbox->m_y+m_checkbox->m_h), false , true , // border, word warp m_irrlicht_window); b->setTabStop(false); @@ -324,7 +326,8 @@ void TrackInfoDialog::onEnterPressedInternal() const int num_laps = (m_spinner == NULL ? -1 : m_spinner->getValue()); const bool reverse_track = m_checkbox == NULL ? false : m_checkbox->getState(); - race_manager->startSingleRace(m_track_ident, num_laps, reverse_track); + race_manager->setReverseTrack(reverse_track); + race_manager->startSingleRace(m_track_ident, num_laps); } // ------------------------------------------------------------------------------------------------------ @@ -336,13 +339,15 @@ GUIEngine::EventPropagation TrackInfoDialog::processEvent(const std::string& eve // Create a copy of member variables we still need, since they will // not be accessible after dismiss: const int num_laps = (m_spinner == NULL ? -1 : m_spinner->getValue()); - const bool reverse_track = m_checkbox == NULL ? false - : m_checkbox->getState(); std::string track_ident = m_track_ident; ModalDialog::dismiss(); - race_manager->startSingleRace(track_ident, num_laps, reverse_track); + race_manager->startSingleRace(track_ident, num_laps); return GUIEngine::EVENT_BLOCK; } + else if (eventSource == "reversecheckbox") + { + race_manager->setReverseTrack(m_checkbox->getState()); + } else if (eventSource == "lapcountspinner") { assert(m_spinner != NULL); From 80ec89375834e66d0a2083a43375f2e6a5e729aa Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 5 Feb 2012 22:24:20 +0000 Subject: [PATCH 42/68] Use singleton-like constructs instead of static pointer to quad set etc. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10809 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/graph_node.cpp | 38 +++++++++++++++----------------------- src/tracks/graph_node.hpp | 13 +++---------- src/tracks/quad_graph.cpp | 21 +++++++++++---------- src/tracks/quad_graph.hpp | 8 ++++---- src/tracks/quad_set.cpp | 17 ++++++++++++----- src/tracks/quad_set.hpp | 34 ++++++++++++++++++++++++++++++---- 6 files changed, 75 insertions(+), 56 deletions(-) diff --git a/src/tracks/graph_node.cpp b/src/tracks/graph_node.cpp index fe4382343..ff9b953a7 100644 --- a/src/tracks/graph_node.cpp +++ b/src/tracks/graph_node.cpp @@ -25,28 +25,19 @@ #include "tracks/quad_graph.hpp" #include "tracks/quad_set.hpp" - -// A static variable that gives a single graph node easy access to -// all quads and avoids unnecessary parameters in many calls. -QuadSet *GraphNode::m_all_quads=NULL; - -// This static variable gives a node access to the graph, and therefore -// to the quad to which a graph node index belongs. -QuadGraph *GraphNode::m_all_nodes=NULL; - // ---------------------------------------------------------------------------- /** Constructor. Saves the quad index which belongs to this graph node. - * \param index Index of the quad to use for this node (in m_all_quads). + * \param index Index of the quad to use for this node (in QuadSet). */ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index) { - assert(quad_indexgetNumberOfQuads()); + assert(quad_indexgetNumberOfQuads()); m_quad_index = quad_index; m_node_index = node_index; m_predecessor = -1; m_distance_from_start = 0; - const Quad &quad = m_all_quads->getQuad(m_quad_index); + const Quad &quad = QuadSet::get()->getQuad(m_quad_index); // FIXME: the following values should depend on the actual orientation // of the quad. ATM we always assume that indices 0,1 are the lower end, // and 2,3 are the upper end. @@ -75,17 +66,17 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index) void GraphNode::addSuccessor(unsigned int to) { m_successor_node.push_back(to); - // m_quad_index is the quad index, so we use m_all_quads - const Quad &this_quad = m_all_quads->getQuad(m_quad_index); - // to is the graph node, so we have to use m_all_nodes to get the right quad - GraphNode &gn = m_all_nodes->getNode(to); - const Quad &next_quad = m_all_nodes->getQuadOfNode(to); + // m_quad_index is the quad index + const Quad &this_quad = QuadSet::get()->getQuad(m_quad_index); + // to is the graph node + GraphNode &gn = QuadGraph::get()->getNode(to); + const Quad &next_quad = QuadGraph::get()->getQuadOfNode(to); // Keep the first predecessor, which is usually the most 'natural' one. if(gn.m_predecessor==-1) gn.m_predecessor = m_node_index; core::vector2df d2 = m_lower_center_2d - - m_all_nodes->getNode(to).m_lower_center_2d; + - QuadGraph::get()->getNode(to).m_lower_center_2d; Vec3 diff = next_quad.getCenter() - this_quad.getCenter(); m_distance_to_next.push_back(d2.getLength()); @@ -107,16 +98,17 @@ void GraphNode::addSuccessor(unsigned int to) // from start of the last node) could be smaller than some of the // paths. This can result in incorrect results for the arrival time // estimation of the AI karts. See trac #354 for details. - if(m_all_nodes->getNode(to).m_distance_from_start==0) + if(QuadGraph::get()->getNode(to).m_distance_from_start==0) { - m_all_nodes->getNode(to).m_distance_from_start = distance_for_next; + QuadGraph::get()->getNode(to).m_distance_from_start + = distance_for_next; } - else if(m_all_nodes->getNode(to).m_distance_from_start + else if(QuadGraph::get()->getNode(to).m_distance_from_start < distance_for_next) { float delta = distance_for_next - - m_all_nodes->getNode(to).getDistanceFromStart(); - m_all_nodes->updateDistancesForAllSuccessors(to, delta); + - QuadGraph::get()->getNode(to).getDistanceFromStart(); + QuadGraph::get()->updateDistancesForAllSuccessors(to, delta); } } } // addSuccessor diff --git a/src/tracks/graph_node.hpp b/src/tracks/graph_node.hpp index 609b2ee90..5c3d5a4b3 100644 --- a/src/tracks/graph_node.hpp +++ b/src/tracks/graph_node.hpp @@ -109,13 +109,6 @@ class GraphNode std::vector< int > m_checkline_requirements; public: - /** Keep a shared pointer so that some asserts and tests can be - * done without adding additional parameters. */ - static QuadSet *m_all_quads; - /** Keep a shared pointer to the graph structure so that each node - * has access to the actual quad to which a node points. */ - static QuadGraph *m_all_nodes; - GraphNode(unsigned int quad_index, unsigned int node_index); void addSuccessor (unsigned int to); void getDistances(const Vec3 &xyz, Vec3 *result); @@ -136,14 +129,14 @@ public: // ------------------------------------------------------------------------ /** Returns the quad of this graph node. */ - const Quad& getQuad() const {return m_all_quads->getQuad(m_quad_index);} + const Quad& getQuad() const {return QuadSet::get()->getQuad(m_quad_index);} // ------------------------------------------------------------------------ /** Returns the i-th. point of a quad. ATM this just returns the vertices * from the quads, but if necessary this method will also consider * rotated quads. So index 0 will always be lower left point, then * counterclockwise. */ const Vec3& operator[](int i) const - {return m_all_quads->getQuad(m_quad_index)[i];} + {return QuadSet::get()->getQuad(m_quad_index)[i];} // ------------------------------------------------------------------------ /** Returns the distance to the j-th. successor. */ float getDistanceToSuccessor(unsigned int j) const @@ -183,7 +176,7 @@ public: * \param index Index of the successor. */ bool ignoreSuccessorForAI(unsigned int i) const { - return m_all_quads->getQuad(m_successor_node[i]).letAIIgnore(); + return QuadSet::get()->getQuad(m_successor_node[i]).letAIIgnore(); }; // ------------------------------------------------------------------------ /** Returns a predecessor for this node. */ diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index 519fa3e57..d3c20de9b 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -50,13 +50,13 @@ QuadGraph::QuadGraph(const std::string &quad_file_name, m_mesh = NULL; m_mesh_buffer = NULL; m_lap_length = 0; - m_all_quads = new QuadSet(quad_file_name); + QuadSet::create(); + QuadSet::get()->init(quad_file_name); if(m_reverse) { - m_all_quads->reverse_all_quads(); + QuadSet::get()->reverse_all_quads(); } m_quad_filename = quad_file_name; - GraphNode::m_all_quads = m_all_quads; - GraphNode::m_all_nodes = this; + m_quad_graph = this; load(graph_file_name); } // QuadGraph @@ -64,7 +64,7 @@ QuadGraph::QuadGraph(const std::string &quad_file_name, /** Destructor, removes all nodes of the graph. */ QuadGraph::~QuadGraph() { - delete m_all_quads; + QuadSet::destroy(); for(unsigned int i=0; iaddSuccessor(from); else m_all_nodes[from]->addSuccessor(to); -} +} // addSuccessor +// ----------------------------------------------------------------------------- /** Loads a quad graph from a file. * \param filename Name of the file to load. */ @@ -93,7 +94,7 @@ void QuadGraph::load(const std::string &filename) // No graph file exist, assume a default loop X -> X+1 // i.e. each quad is part of the graph exactly once. // First create an empty graph node for each quad: - for(unsigned int i=0; igetNumberOfQuads(); i++) + for(unsigned int i=0; igetNumberOfQuads(); i++) m_all_nodes.push_back(new GraphNode(i, m_all_nodes.size())); // Then set the default loop: setDefaultSuccessors(); @@ -448,7 +449,7 @@ void QuadGraph::createMesh(bool show_invisible, ind[6*i+4] = 4*i+2; ind[6*i+5] = 4*i+3; i++; - } // for i=1; iappend(new_v, n*4, ind, n*6); @@ -462,7 +463,7 @@ void QuadGraph::createMesh(bool show_invisible, // Now scale the length (distance between vertix 0 and 3 // and between 1 and 2) to be 'length': Vec3 bb_min, bb_max; - m_all_quads->getBoundingBox(&bb_min, &bb_max); + QuadSet::get()->getBoundingBox(&bb_min, &bb_max); // Length of the lap line about 3% of the 'height' // of the track. const float length=(bb_max.getZ()-bb_min.getZ())*0.03f; @@ -794,7 +795,7 @@ video::ITexture *QuadGraph::makeMiniMap(const core::dimension2du &dimension, // --------------- scene::ICameraSceneNode *camera = irr_driver->addCameraSceneNode(); Vec3 bb_min, bb_max; - m_all_quads->getBoundingBox(&bb_min, &bb_max); + QuadSet::get()->getBoundingBox(&bb_min, &bb_max); Vec3 center = (bb_max+bb_min)*0.5f; float dx = bb_max.getX()-bb_min.getX(); diff --git a/src/tracks/quad_graph.hpp b/src/tracks/quad_graph.hpp index 7acee5844..6a5f7e719 100644 --- a/src/tracks/quad_graph.hpp +++ b/src/tracks/quad_graph.hpp @@ -56,8 +56,6 @@ private: /** The actual graph data structure. */ std::vector m_all_nodes; - /** The set of all quads. */ - QuadSet *m_all_quads; /** For debug mode only: the node of the debug mesh. */ scene::ISceneNode *m_node; /** For debug only: the mesh of the debug mesh. */ @@ -134,7 +132,9 @@ public: const bool reverse) { assert(m_quad_graph==NULL); - m_quad_graph = new QuadGraph(quad_file_name, graph_file_name, reverse); + // assignment to m_quad_graph is done in the constructor, since + // functions called from the constructor need it to be defined. + new QuadGraph(quad_file_name, graph_file_name, reverse); } // create // ---------------------------------------------------------------------- /** Cleans up the quad graph. It is possible that this function is called @@ -167,7 +167,7 @@ public: // ---------------------------------------------------------------------- /** Returns the quad that belongs to a graph node. */ const Quad& getQuadOfNode(unsigned int j) const - { return m_all_quads->getQuad(m_all_nodes[j]->getIndex()); } + { return QuadSet::get()->getQuad(m_all_nodes[j]->getIndex()); } // ---------------------------------------------------------------------- /** Returns the quad that belongs to a graph node. */ GraphNode& getNode(unsigned int j) const{ return *m_all_nodes[j]; } diff --git a/src/tracks/quad_set.cpp b/src/tracks/quad_set.cpp index 05c6aa46b..9f1af0957 100644 --- a/src/tracks/quad_set.cpp +++ b/src/tracks/quad_set.cpp @@ -25,11 +25,14 @@ #include "io/xml_node.hpp" #include "utils/string_utils.hpp" -/** Constructor, loads the quad set from a file. - * \param filename filename to load. +QuadSet *QuadSet::m_quad_set = NULL; + +/** Constructor, loads the quad set from a file. Assigns a pointer + * to this instance to m_quad_set, so that it can be accessed using get(). */ -QuadSet::QuadSet(const std::string& filename) { - load(filename); +QuadSet::QuadSet() +{ + m_quad_set = this; } // QuadSet // ----------------------------------------------------------------------------- @@ -42,6 +45,7 @@ QuadSet::~QuadSet() delete m_all_quads[i]; } m_all_quads.clear(); + m_quad_set = NULL; } // ~QuadSet // ----------------------------------------------------------------------------- @@ -76,7 +80,10 @@ void QuadSet::getPoint(const XMLNode *xml, const std::string &attribute_name, } // getPoint // ----------------------------------------------------------------------------- -void QuadSet::load(const std::string &filename) +/** Loads the set of all quads from the speciified filename. + * \param filename The absolute filename to load the quad file from. + */ +void QuadSet::init(const std::string &filename) { m_min = Vec3( 99999, 99999, 99999); m_max = Vec3(-99999, -99999, -99999); diff --git a/src/tracks/quad_set.hpp b/src/tracks/quad_set.hpp index 2d2006b26..974ee302f 100644 --- a/src/tracks/quad_set.hpp +++ b/src/tracks/quad_set.hpp @@ -36,30 +36,56 @@ private: /** The 2d bounding box, used for hashing. */ Vec3 m_min; Vec3 m_max; + /** The list of all quads. */ std::vector m_all_quads; - void load (const std::string &filename); + + /** Pointer to the one instance of a quad set. */ + static QuadSet *m_quad_set; + void getPoint(const XMLNode *xml, const std::string &attribute_name, Vec3 *result) const; + QuadSet(); + ~QuadSet(); public: static const int QUAD_NONE=-1; - QuadSet (const std::string& filename); - ~QuadSet (); + void init (const std::string &filename); void reverse_all_quads(); int getCurrentQuad(const Vec3& p, int oldQuad) const; + // ------------------------------------------------------------------------ + /** Creates one instance of the quad set. */ + static void create() + { + assert(m_quad_set==NULL); + m_quad_set = new QuadSet(); + } + // ------------------------------------------------------------------------ + /** Destroys the one instance of a quad set. */ + static void destroy() + { + delete m_quad_set; m_quad_set = NULL; + } + // ------------------------------------------------------------------------ + /** Static member function to access the QuadSet instance. */ + static QuadSet *get() { return m_quad_set; } + // ------------------------------------------------------------------------ + /** Returns the quad with a given index number. */ const Quad& getQuad(int n) const {return *(m_all_quads[n]); } - + // ------------------------------------------------------------------------ /** Return the minimum and maximum coordinates of this quad set. */ void getBoundingBox(Vec3 *min, Vec3 *max) { *min=m_min; *max=m_max; } + // ------------------------------------------------------------------------ /** Returns the number of quads. */ unsigned int getNumberOfQuads() const {return (unsigned int)m_all_quads.size(); } + // ------------------------------------------------------------------------ /** Returns the center of quad n. */ const Vec3& getCenterOfQuad(int n) const {return m_all_quads[n]->getCenter(); } + // ------------------------------------------------------------------------ /** Returns the n-th. quad. */ const Quad& getQuad(int n) {return *(m_all_quads[n]); } }; // QuadSet From b5bb733e190890b24c618fb968b6a2ea765db983 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 5 Feb 2012 22:33:17 +0000 Subject: [PATCH 43/68] Make the karts start just ahead of the starting line in reverse mode. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10810 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/quad_graph.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index d3c20de9b..362996af3 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -330,8 +330,13 @@ void QuadGraph::setDefaultStartPositions(AlignedArray float sidewards_distance, float upwards_distance) const { - // Node 0 is always the node on which the start line is. - int current_node = getNode(0).getPredecessor(); + // In non-reverse mode: node 0 is the node on which the start line is. + // So get its predecessor (which is therefore just + // before the start line) to find the first quad + // to place karts on. + // In reverse mode, karts can start to placed on quad 0. + int current_node = m_reverse ? getNode(0).getIndex() + : getNode(0).getPredecessor(); float distance_from_start = 0.1f+forwards_distance; From 59c5537fe5aadedba8c62d250432b7f0a50db529 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Mon, 6 Feb 2012 21:12:10 +0000 Subject: [PATCH 44/68] Fixed crash in case of using -N without --reverse on the command line. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10812 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/race/race_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index cd5d6f274..302c3156a 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -55,6 +55,7 @@ RaceManager::RaceManager() m_minor_mode = MINOR_MODE_NORMAL_RACE; m_track_number = 0; m_coin_target = 0; + setReverseTrack(false); setTrack("jungle"); m_default_ai_list.clear(); setNumLocalPlayers(0); From f2d5ca5203f5adde093b43a85300b7bf1eeadd0e Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 7 Feb 2012 03:08:43 +0000 Subject: [PATCH 45/68] 1) Set reverse state to false if no reverse track is available (otherwise after racing one track in reverse mode, the next track without reverse available will still have reverse flag set). 2) Set the state of the checkbox to the previsouly selected reverse status (which makes it a bit more convenient if you want to replay with the same settings). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10818 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/states_screens/dialogs/track_info_dialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/states_screens/dialogs/track_info_dialog.cpp b/src/states_screens/dialogs/track_info_dialog.cpp index ff68b4fb7..44281df1a 100644 --- a/src/states_screens/dialogs/track_info_dialog.cpp +++ b/src/states_screens/dialogs/track_info_dialog.cpp @@ -161,7 +161,7 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin //~ m_checkbox->setText( _("Reverse track") ); m_widgets.push_back(m_checkbox); m_checkbox->add(); - m_checkbox->setState(false); + m_checkbox->setState(race_manager->getReverseTrack()); m_checkbox->getIrrlichtElement()->setTabStop(true); m_checkbox->getIrrlichtElement()->setTabGroup(false); stringw text_reverse = _("Reverse"); @@ -178,6 +178,7 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin else { m_checkbox = NULL; + race_manager->setReverseTrack(false); } // ---- Start button From 3659b1466702298fb9332d6643844800dcb6ab8e Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 7 Feb 2012 03:10:43 +0000 Subject: [PATCH 46/68] Redone 'distance from start' calculation to use the proper graph structure (and not to assume that the quads/graph nodes will be added in a specific order, i.e. in the order in which they are connected). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10819 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/graph_node.cpp | 42 ++++----------------- src/tracks/quad_graph.cpp | 78 ++++++++++++++++++++++++++++++++------- src/tracks/quad_graph.hpp | 5 ++- 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/tracks/graph_node.cpp b/src/tracks/graph_node.cpp index ff9b953a7..465a449ae 100644 --- a/src/tracks/graph_node.cpp +++ b/src/tracks/graph_node.cpp @@ -35,7 +35,7 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index) m_quad_index = quad_index; m_node_index = node_index; m_predecessor = -1; - m_distance_from_start = 0; + m_distance_from_start = -1.0f; const Quad &quad = QuadSet::get()->getQuad(m_quad_index); // FIXME: the following values should depend on the actual orientation @@ -75,42 +75,13 @@ void GraphNode::addSuccessor(unsigned int to) // Keep the first predecessor, which is usually the most 'natural' one. if(gn.m_predecessor==-1) gn.m_predecessor = m_node_index; - core::vector2df d2 = m_lower_center_2d - - QuadGraph::get()->getNode(to).m_lower_center_2d; - Vec3 diff = next_quad.getCenter() - this_quad.getCenter(); - m_distance_to_next.push_back(d2.getLength()); - - float theta = atan2(diff.getX(), diff.getZ()); - m_angle_to_next.push_back(theta); + Vec3 d = m_lower_center - QuadGraph::get()->getNode(to).m_lower_center; + m_distance_to_next.push_back(d.length()); + + Vec3 diff = next_quad.getCenter() - this_quad.getCenter(); + m_angle_to_next.push_back(atan2(diff.getX(), diff.getZ())); - // The length of this quad is the average of the left and right side - float distance_to_next = ( this_quad[2].distance(this_quad[1]) - + this_quad[3].distance(this_quad[0]) ) *0.5f; - // The distance from start for the successor node - if(to!=0) - { - float distance_for_next = m_distance_from_start+distance_to_next; - // If the successor node does not have a distance from start defined, - // update its distance. Otherwise if the node already has a distance, - // it is potentially necessary to update its distance from start: - // without this the length of the track (as taken by the distance - // from start of the last node) could be smaller than some of the - // paths. This can result in incorrect results for the arrival time - // estimation of the AI karts. See trac #354 for details. - if(QuadGraph::get()->getNode(to).m_distance_from_start==0) - { - QuadGraph::get()->getNode(to).m_distance_from_start - = distance_for_next; - } - else if(QuadGraph::get()->getNode(to).m_distance_from_start - < distance_for_next) - { - float delta = distance_for_next - - QuadGraph::get()->getNode(to).getDistanceFromStart(); - QuadGraph::get()->updateDistancesForAllSuccessors(to, delta); - } - } } // addSuccessor // ---------------------------------------------------------------------------- @@ -196,6 +167,7 @@ void GraphNode::getDistances(const Vec3 &xyz, Vec3 *result) else result->setX(-(closest-xyz2d).getLength()); // to the left result->setZ( m_distance_from_start + (closest-m_lower_center_2d).getLength()); + printf("get distances %f %f\n", result->getX(), result->getZ()); } // getDistances // ---------------------------------------------------------------------------- diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index 362996af3..99d36ad98 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -185,21 +185,28 @@ void QuadGraph::load(const std::string &filename) } delete xml; - // Define the track length + setDefaultSuccessors(); + + // The track exporter always exports quad 0 as first quad after (or at) + // the start line (start line is lower side of quad 0). In reverse mode + // the start quad is the predecessor of node 0. + unsigned int start_node = m_reverse ? m_all_nodes[0]->getPredecessor() + : 0; + computeDistanceFromStart(start_node, 0.0f); + + // Define the track length as the maximum at the end of a quad + // (i.e. distance_from_start + length till successor 0). + m_lap_length = -1; for(unsigned int i=0; igetSuccessor(0)==0) - { - m_lap_length = m_all_nodes[i]->getDistanceFromStart() + float l = m_all_nodes[i]->getDistanceFromStart() + m_all_nodes[i]->getDistanceToSuccessor(0); - break; - } + if(l > m_lap_length) + m_lap_length = l; } - setDefaultSuccessors(); } // load // ---------------------------------------------------------------------------- - /** * Finds which checklines must be visited before driving on this quad * (useful for rescue) @@ -581,7 +588,52 @@ void QuadGraph::getSuccessors(int node_number, } // getSuccessors // ---------------------------------------------------------------------------- -/** Increases +void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance) +{ + GraphNode *gn = m_all_nodes[node]; + float current_distance = gn->getDistanceFromStart(); + + // If this node already has a distance defined, check if the new distance + // is longer, and if so adjust all following nodes. Without this the + // length of the track (as taken by the distance from start of the last + // node) could be smaller than some of the paths. This can result in + // incorrect results for the arrival time estimation of the AI karts. + // See trac #354 for details. + // Then there is no need to test/adjust any more nodes. + if(current_distance>=0) + { + if(current_distancegetIndex(), delta); + } + return; + } + + // Otherwise this node has no distance defined yet. Set the new + // distance, and recursively update all following nodes. + gn->setDistanceFromStart(new_distance); + + for(unsigned int i=0; igetNumberOfSuccessors(); i++) + { + GraphNode *gn_next = m_all_nodes[gn->getSuccessor(i)]; + // The start node (only node with distance 0) is reached again, + // recursion can stop now + if(gn_next->getDistanceFromStart()==0) + continue; + + computeDistanceFromStart(gn_next->getIndex(), + new_distance + gn->getDistanceToSuccessor(i)); + } // for i +} // computeDistanceFromStart + +// ---------------------------------------------------------------------------- +/** Increases the distance from start for all nodes that are directly or + * indirectly a successor of the given node. This code is used when two + * branches merge together, but since the latest 'fork' indicates a longer + * distance from start. + * \param indx Index of the node for which to increase the distance. + * \param delta Amount by which to increase the distance. */ void QuadGraph::updateDistancesForAllSuccessors(unsigned int indx, float delta) { @@ -590,11 +642,9 @@ void QuadGraph::updateDistancesForAllSuccessors(unsigned int indx, float delta) for(unsigned int i=0; i Date: Tue, 7 Feb 2012 04:15:13 +0000 Subject: [PATCH 47/68] Removed dead code. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10820 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/items/rubber_ball.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/items/rubber_ball.cpp b/src/items/rubber_ball.cpp index 4b88fcd5c..b81e31fb0 100644 --- a/src/items/rubber_ball.cpp +++ b/src/items/rubber_ball.cpp @@ -224,22 +224,7 @@ void RubberBall::getNextControlPoint() m_length_cp_2_3 = dist; const Quad &quad = QuadGraph::get()->getQuadOfNode(m_last_aimed_graph_node); - Vec3 aim = quad.getCenter(); - // If we are close enough for the ball to hop faster, adjust the position - // relative to the center of the track depending on where the target is: - - // if(m_fast_ping) - if(0) - { - LinearWorld *world = dynamic_cast(World::getWorld()); - float r = world->getTrackSector(m_target->getWorldKartId()) - .getRelativeDistanceToCenter(); - aim -= m_st_early_target_factor * r - * QuadGraph::get()->getNode(m_last_aimed_graph_node) - .getCenterToRightVector(); - } - - m_control_points[3] = aim; + m_control_points[3] = quad.getCenter(); } // getNextControlPoint // ---------------------------------------------------------------------------- From 92ef262bb04d32a325ea6ce8a82ca25871b34e50 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 7 Feb 2012 05:15:19 +0000 Subject: [PATCH 48/68] Removed reversal of quads, instead fixed handling of the data structures that depend on the orientation to properly handle reverse tracks. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10821 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/graph_node.cpp | 19 ++++++++++++------- src/tracks/graph_node.hpp | 4 ---- src/tracks/quad.cpp | 10 ---------- src/tracks/quad.hpp | 2 -- src/tracks/quad_graph.cpp | 3 --- src/tracks/quad_set.cpp | 8 +------- src/tracks/quad_set.hpp | 2 -- 7 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/tracks/graph_node.cpp b/src/tracks/graph_node.cpp index 465a449ae..2475c49d1 100644 --- a/src/tracks/graph_node.cpp +++ b/src/tracks/graph_node.cpp @@ -44,17 +44,22 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index) // The width is the average width at the beginning and at the end. m_width = ( (quad[1]-quad[0]).length() + (quad[3]-quad[2]).length() ) * 0.5f; - m_lower_center = (quad[0]+quad[1]) * 0.5f; - m_upper_center = (quad[2]+quad[3]) * 0.5f; + if(QuadGraph::get()->isReverse()) + { + m_lower_center = (quad[2]+quad[3]) * 0.5f; + m_upper_center = (quad[0]+quad[1]) * 0.5f; + } + else + { + m_lower_center = (quad[0]+quad[1]) * 0.5f; + m_upper_center = (quad[2]+quad[3]) * 0.5f; + } m_line = core::line2df(m_lower_center.getX(), m_lower_center.getZ(), m_upper_center.getX(), m_upper_center.getZ() ); // Only this 2d point is needed later m_lower_center_2d = core::vector2df(m_lower_center.getX(), m_lower_center.getZ() ); - // The vector from the center of the quad to the middle of the right - // side of the quad - m_center_to_right = (quad[1]+quad[2])*0.5f - quad.getCenter(); } // GraphNode // ---------------------------------------------------------------------------- @@ -166,8 +171,8 @@ void GraphNode::getDistances(const Vec3 &xyz, Vec3 *result) result->setX( (closest-xyz2d).getLength()); // to the right else result->setX(-(closest-xyz2d).getLength()); // to the left - result->setZ( m_distance_from_start + (closest-m_lower_center_2d).getLength()); - printf("get distances %f %f\n", result->getX(), result->getZ()); + result->setZ( m_distance_from_start + + (closest-m_lower_center_2d).getLength()); } // getDistances // ---------------------------------------------------------------------------- diff --git a/src/tracks/graph_node.hpp b/src/tracks/graph_node.hpp index 5c3d5a4b3..29841a689 100644 --- a/src/tracks/graph_node.hpp +++ b/src/tracks/graph_node.hpp @@ -193,10 +193,6 @@ public: return m_path_to_node.size()>0 ? m_path_to_node[n] : 0; } // getSuccesorToReach // ------------------------------------------------------------------------ - /** Returns a vector from the center of the node to the middle of the - * right side. */ - const Vec3 &getCenterToRightVector() const { return m_center_to_right; } - // ------------------------------------------------------------------------ /** Returns the checkline requirements of this graph node. */ const std::vector& getChecklineRequirements() const { return m_checkline_requirements; } diff --git a/src/tracks/quad.cpp b/src/tracks/quad.cpp index 3f9dc24ce..244ce94ab 100644 --- a/src/tracks/quad.cpp +++ b/src/tracks/quad.cpp @@ -132,13 +132,3 @@ void Quad::transform(const btTransform &t, Quad *result) const result->m_p[3].getY()) ); } // transform -// ---------------------------------------------------------------------------- -/** Reverse the quad */ -void Quad::reverse() { - Vec3 tmp = m_p[0]; - m_p[0] = m_p[2]; - m_p[2] = tmp; - tmp = m_p[1]; - m_p[1] = m_p[3]; - m_p[3] = tmp; -} diff --git a/src/tracks/quad.hpp b/src/tracks/quad.hpp index 47566ded9..ab8d3ebb6 100644 --- a/src/tracks/quad.hpp +++ b/src/tracks/quad.hpp @@ -76,7 +76,5 @@ public: /** True if this quad should be ignored by the AI. */ bool letAIIgnore() const { return m_ai_ignore; } - /** Reverse the quad */ - void reverse(); }; // class Quad #endif diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index 99d36ad98..6a904e72b 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -52,9 +52,6 @@ QuadGraph::QuadGraph(const std::string &quad_file_name, m_lap_length = 0; QuadSet::create(); QuadSet::get()->init(quad_file_name); - if(m_reverse) { - QuadSet::get()->reverse_all_quads(); - } m_quad_filename = quad_file_name; m_quad_graph = this; load(graph_file_name); diff --git a/src/tracks/quad_set.cpp b/src/tracks/quad_set.cpp index 9f1af0957..681b4c031 100644 --- a/src/tracks/quad_set.cpp +++ b/src/tracks/quad_set.cpp @@ -48,13 +48,7 @@ QuadSet::~QuadSet() m_quad_set = NULL; } // ~QuadSet -// ----------------------------------------------------------------------------- -void reverse_quad(Quad* q) { - q->reverse(); -} -void QuadSet::reverse_all_quads() { - for_each(m_all_quads.begin(),m_all_quads.end(),reverse_quad); -} +// -----------------------------------------------------------------------------} /** This function interprets a point specification as an attribute in the xml quadset file. It understands two different specifications: p1="n:p" : get point p from square n (n, p integers) diff --git a/src/tracks/quad_set.hpp b/src/tracks/quad_set.hpp index 974ee302f..c87803f94 100644 --- a/src/tracks/quad_set.hpp +++ b/src/tracks/quad_set.hpp @@ -52,8 +52,6 @@ public: static const int QUAD_NONE=-1; void init (const std::string &filename); - void reverse_all_quads(); - int getCurrentQuad(const Vec3& p, int oldQuad) const; // ------------------------------------------------------------------------ /** Creates one instance of the quad set. */ static void create() From 7bdcb9d6819b4aee68115fe4fd5876ccb37b0a57 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 7 Feb 2012 05:16:05 +0000 Subject: [PATCH 49/68] Updated comment. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10822 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/graph_node.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tracks/graph_node.cpp b/src/tracks/graph_node.cpp index 2475c49d1..6edadac5c 100644 --- a/src/tracks/graph_node.cpp +++ b/src/tracks/graph_node.cpp @@ -38,9 +38,9 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index) m_distance_from_start = -1.0f; const Quad &quad = QuadSet::get()->getQuad(m_quad_index); - // FIXME: the following values should depend on the actual orientation + // The following values should depend on the actual orientation // of the quad. ATM we always assume that indices 0,1 are the lower end, - // and 2,3 are the upper end. + // and 2,3 are the upper end (or the reverse if reverse mode is selected). // The width is the average width at the beginning and at the end. m_width = ( (quad[1]-quad[0]).length() + (quad[3]-quad[2]).length() ) * 0.5f; From c3a9c03b8bff4ec078fefa80ed1c3620aa1177bd Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 7 Feb 2012 05:32:20 +0000 Subject: [PATCH 50/68] Worked around the problem that the reverse check box could not be selected by mouse on 800x600 resolution (the checkbox was then outside of the dialog window). A proper solution (imho) should be to convert the dialog into a full-screen menu (which would also be consistent with all other menus). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10823 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/states_screens/dialogs/track_info_dialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/states_screens/dialogs/track_info_dialog.cpp b/src/states_screens/dialogs/track_info_dialog.cpp index 44281df1a..49041a8e0 100644 --- a/src/states_screens/dialogs/track_info_dialog.cpp +++ b/src/states_screens/dialogs/track_info_dialog.cpp @@ -151,7 +151,7 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin if (reverse_available) { m_checkbox = new CheckBoxWidget(); - m_checkbox->m_x = m_area.getWidth()/2 - 400; + m_checkbox->m_x = 0; m_checkbox->m_y = (y2+y3)/2; m_checkbox->m_w = 60; m_checkbox->m_h = 60; From 01458892f0b6179b74ad666aadbdd5e887a4d891 Mon Sep 17 00:00:00 2001 From: mcmic Date: Wed, 8 Feb 2012 12:48:07 +0000 Subject: [PATCH 51/68] Now reversing check structures order. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10824 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/check_manager.cpp | 22 +++++++++++++++++++++- src/tracks/check_structure.hpp | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/tracks/check_manager.cpp b/src/tracks/check_manager.cpp index 167c69b99..0f14ed30a 100644 --- a/src/tracks/check_manager.cpp +++ b/src/tracks/check_manager.cpp @@ -19,6 +19,7 @@ #include "tracks/check_manager.hpp" #include +#include #include "io/xml_node.hpp" #include "tracks/ambient_light_sphere.hpp" @@ -67,7 +68,26 @@ CheckManager::~CheckManager() /** Reverse checks order. */ void CheckManager::reverse() { - // FIXME + std::map > structures_to_change_state; + std::vector::iterator it; + for(unsigned int i=0;i::const_iterator it = m_all_checks[i]->m_check_structures_to_change_state.begin(); + it != m_all_checks[i]->m_check_structures_to_change_state.end(); ++it) + { + if(*it>=0) + { + structures_to_change_state[*it].push_back(i); + } + } + } + for(unsigned int i=0;im_check_structures_to_change_state.clear(); + m_all_checks[i]->m_check_structures_to_change_state.resize(structures_to_change_state[i].size()); + copy(structures_to_change_state[i].begin(),structures_to_change_state[i].end(), + m_all_checks[i]->m_check_structures_to_change_state.begin()); + } } // reverse // ---------------------------------------------------------------------------- diff --git a/src/tracks/check_structure.hpp b/src/tracks/check_structure.hpp index 0fc4b90be..3a13e77a3 100644 --- a/src/tracks/check_structure.hpp +++ b/src/tracks/check_structure.hpp @@ -47,6 +47,7 @@ class CheckManager; */ class CheckStructure { +friend class CheckManager; public: /** Different types of check structures: * ACTIVATE: Activates another check structure (independent of From 45bb8ceb40d250f59aca41174f5558d5281c7a3b Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 9 Feb 2012 11:21:07 +0000 Subject: [PATCH 52/68] Bugfix: In reverse mode, distance along track started with the wrong graph node, causing the first lap crossing not being detected. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10831 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/quad_graph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index 6a904e72b..48788f04d 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -187,7 +187,7 @@ void QuadGraph::load(const std::string &filename) // The track exporter always exports quad 0 as first quad after (or at) // the start line (start line is lower side of quad 0). In reverse mode // the start quad is the predecessor of node 0. - unsigned int start_node = m_reverse ? m_all_nodes[0]->getPredecessor() + unsigned int start_node = m_reverse ? m_all_nodes[0]->getSuccessor(0) : 0; computeDistanceFromStart(start_node, 0.0f); From ff67a5cf4e002d9321fe2d3c18b07f7ef8f33c40 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 9 Feb 2012 21:14:32 +0000 Subject: [PATCH 53/68] Removed the usage of friend declaration. CheckStructure dependencies are now not read in CheckStructure anymore, instead they are set by the CheckManager depending on the direction of the track. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10832 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/check_manager.cpp | 53 +++++++++++++++++----------------- src/tracks/check_manager.hpp | 1 - src/tracks/check_structure.cpp | 14 ++++----- src/tracks/check_structure.hpp | 12 ++++++-- src/tracks/track.cpp | 3 -- 5 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/tracks/check_manager.cpp b/src/tracks/check_manager.cpp index 0f14ed30a..c69876fea 100644 --- a/src/tracks/check_manager.cpp +++ b/src/tracks/check_manager.cpp @@ -52,6 +52,32 @@ CheckManager::CheckManager(const XMLNode &node, Track *track) else printf("Unknown check structure '%s' - ignored.\n", type.c_str()); } // for i check_structures_to_change_state; + + check_node->get("other-ids", &check_structures_to_change_state); + // Backwards compatibility to tracks exported with older versions of + // the track exporter + if(check_structures_to_change_state.size()==0) + check_node->get("other-id", &check_structures_to_change_state); + std::vector::iterator it; + for(it=check_structures_to_change_state.begin(); + it != check_structures_to_change_state.end(); it++) + { + if(QuadGraph::get()->isReverse()) + m_all_checks[*it]->addSuccessor(i); + else + m_all_checks[i]->addSuccessor(*it); + } + + } } // CheckManager // ---------------------------------------------------------------------------- @@ -65,33 +91,6 @@ CheckManager::~CheckManager() // ---------------------------------------------------------------------------- -/** Reverse checks order. */ -void CheckManager::reverse() -{ - std::map > structures_to_change_state; - std::vector::iterator it; - for(unsigned int i=0;i::const_iterator it = m_all_checks[i]->m_check_structures_to_change_state.begin(); - it != m_all_checks[i]->m_check_structures_to_change_state.end(); ++it) - { - if(*it>=0) - { - structures_to_change_state[*it].push_back(i); - } - } - } - for(unsigned int i=0;im_check_structures_to_change_state.clear(); - m_all_checks[i]->m_check_structures_to_change_state.resize(structures_to_change_state[i].size()); - copy(structures_to_change_state[i].begin(),structures_to_change_state[i].end(), - m_all_checks[i]->m_check_structures_to_change_state.begin()); - } -} // reverse - -// ---------------------------------------------------------------------------- - /** Resets all checks. */ void CheckManager::reset(const Track &track) { diff --git a/src/tracks/check_manager.hpp b/src/tracks/check_manager.hpp index fba3c9894..0f9a9c45e 100644 --- a/src/tracks/check_manager.hpp +++ b/src/tracks/check_manager.hpp @@ -39,7 +39,6 @@ public: ~CheckManager(); void update(float dt); void reset(const Track &track); - void reverse(); int getCheckStructureCount() const { return m_all_checks.size(); } diff --git a/src/tracks/check_structure.cpp b/src/tracks/check_structure.cpp index c8caf4d57..98e88940b 100644 --- a/src/tracks/check_structure.cpp +++ b/src/tracks/check_structure.cpp @@ -33,6 +33,13 @@ CheckStructure::CheckStructure(CheckManager *check_manager, { m_index = index; m_check_manager = check_manager; + m_check_type = CT_NEW_LAP; + + // This structure is actually filled by the check manager (necessary + // in order to support track reversing). + m_check_structures_to_change_state.clear(); + m_same_group.clear(); + std::string kind; node.get("kind", &kind); if(kind=="lap") @@ -47,14 +54,7 @@ CheckStructure::CheckStructure(CheckManager *check_manager, { printf("Unknown check structure '%s' - ignored.\n", kind.c_str()); } - m_check_structures_to_change_state.clear(); - node.get("other-ids", &m_check_structures_to_change_state); - // Backwards compatibility to tracks exported with older versions of - // the track exporter - if(m_check_structures_to_change_state.size()==0) - node.get("other-id", &m_check_structures_to_change_state); - m_same_group.clear(); node.get("same-group", &m_same_group); // Make sure that the index of this check structure is included in // the same_group list. While this should be guaranteed by the diff --git a/src/tracks/check_structure.hpp b/src/tracks/check_structure.hpp index 3a13e77a3..99ae2f5b8 100644 --- a/src/tracks/check_structure.hpp +++ b/src/tracks/check_structure.hpp @@ -47,7 +47,6 @@ class CheckManager; */ class CheckStructure { -friend class CheckManager; public: /** Different types of check structures: * ACTIVATE: Activates another check structure (independent of @@ -113,13 +112,20 @@ public: * \param indx Index of the kart, can be used to store kart specific * additional data. */ - virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx)=0; + virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, + int indx)=0; virtual void trigger(unsigned int kart_index); virtual void reset(const Track &track); + // ------------------------------------------------------------------------ /** Returns the type of this check structure. */ CheckType getType() const { return m_check_type; } - + // ------------------------------------------------------------------------ + /** Adds the index of a successor check structure which will get triggered + * by this check structure. */ + void addSuccessor(unsigned int i) { + m_check_structures_to_change_state.push_back(i); + } // addSuccessor }; // CheckStructure #endif diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 254396666..dcdd38fc3 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1316,9 +1316,6 @@ void Track::loadTrackModel(World* parent, bool reverse_track, else if(name=="checks") { m_check_manager = new CheckManager(*node, this); - if(reverse_track) { - m_check_manager->reverse(); - } } else if (name=="particle-emitter") { From 8a0fe903a43b32ac76d3a57dcda7f0def13602a6 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 12 Feb 2012 21:25:06 +0000 Subject: [PATCH 54/68] Use singleton constructions for check manager. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10837 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/ambient_light_sphere.cpp | 7 ++---- src/tracks/ambient_light_sphere.hpp | 3 +-- src/tracks/check_lap.cpp | 6 ++--- src/tracks/check_lap.hpp | 3 +-- src/tracks/check_line.cpp | 8 +++--- src/tracks/check_line.hpp | 3 +-- src/tracks/check_manager.cpp | 18 +++++++++---- src/tracks/check_manager.hpp | 39 ++++++++++++++++++++++------- src/tracks/check_sphere.cpp | 5 ++-- src/tracks/check_sphere.hpp | 3 +-- src/tracks/check_structure.cpp | 12 ++++----- src/tracks/check_structure.hpp | 6 +---- src/tracks/quad_graph.cpp | 2 +- src/tracks/track.cpp | 25 ++++++++---------- src/tracks/track.hpp | 19 +++++--------- 15 files changed, 79 insertions(+), 80 deletions(-) diff --git a/src/tracks/ambient_light_sphere.cpp b/src/tracks/ambient_light_sphere.cpp index b569fd080..21e60c678 100644 --- a/src/tracks/ambient_light_sphere.cpp +++ b/src/tracks/ambient_light_sphere.cpp @@ -28,14 +28,11 @@ #include "tracks/track.hpp" /** Constructor for a checksphere. - * \param check_manager Pointer to the check manager, which is needed when - * resetting e.g. new lap counters. * \param node XML node containing the parameters for this checkline. */ -AmbientLightSphere::AmbientLightSphere(CheckManager *check_manager, - const XMLNode &node, +AmbientLightSphere::AmbientLightSphere(const XMLNode &node, unsigned int index) - : CheckSphere(check_manager, node, index) + : CheckSphere(node, index) { m_ambient_color = video::SColor(255, 0, 255, 0); // green m_inner_radius2 = 1; diff --git a/src/tracks/ambient_light_sphere.hpp b/src/tracks/ambient_light_sphere.hpp index 800ce7853..5c793ca9e 100644 --- a/src/tracks/ambient_light_sphere.hpp +++ b/src/tracks/ambient_light_sphere.hpp @@ -49,8 +49,7 @@ private: * inner radius. */ video::SColor m_ambient_color; public: - AmbientLightSphere(CheckManager *check_manager, - const XMLNode &node, unsigned int index); + AmbientLightSphere(const XMLNode &node, unsigned int index); virtual ~AmbientLightSphere() {}; virtual void update(float dt); virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, diff --git a/src/tracks/check_lap.cpp b/src/tracks/check_lap.cpp index 032e292c3..7865a712e 100644 --- a/src/tracks/check_lap.cpp +++ b/src/tracks/check_lap.cpp @@ -23,7 +23,6 @@ #include "io/xml_node.hpp" #include "modes/linear_world.hpp" #include "race/race_manager.hpp" -#include "tracks/check_manager.hpp" #include "tracks/track.hpp" /** Constructor for a lap line. @@ -31,9 +30,8 @@ * resetting e.g. new lap counters. * \param node XML node containing the parameters for this checkline. */ -CheckLap::CheckLap(CheckManager *check_manager, const XMLNode &node, - unsigned int index) - : CheckStructure(check_manager, node, index) +CheckLap::CheckLap(const XMLNode &node, unsigned int index) + : CheckStructure(node, index) { // Note that when this is called the karts have not been allocated // in world, so we can't call world->getNumKarts() diff --git a/src/tracks/check_lap.hpp b/src/tracks/check_lap.hpp index baa2bfbd6..554a1d3db 100644 --- a/src/tracks/check_lap.hpp +++ b/src/tracks/check_lap.hpp @@ -37,8 +37,7 @@ private: std::vector m_previous_distance; public: - CheckLap(CheckManager *check_manager, const XMLNode &node, - unsigned int index); + CheckLap(const XMLNode &node, unsigned int index); virtual ~CheckLap() {}; virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx); diff --git a/src/tracks/check_line.cpp b/src/tracks/check_line.cpp index 3c28cb98a..2b39ede55 100644 --- a/src/tracks/check_line.cpp +++ b/src/tracks/check_line.cpp @@ -27,13 +27,11 @@ #include "race/race_manager.hpp" /** Constructor for a checkline. - * \param check_manager Pointer to the check manager, which is needed when - * resetting e.g. new lap counters. * \param node XML node containing the parameters for this checkline. + * \param index Index of this check structure in the check manager. */ -CheckLine::CheckLine(CheckManager *check_manager, const XMLNode &node, - unsigned int index) - : CheckStructure(check_manager, node, index) +CheckLine::CheckLine(const XMLNode &node, unsigned int index) + : CheckStructure(node, index) { // Note that when this is called the karts have not been allocated // in world, so we can't call world->getNumKarts() diff --git a/src/tracks/check_line.hpp b/src/tracks/check_line.hpp index d2ae4970a..ad158f51b 100644 --- a/src/tracks/check_line.hpp +++ b/src/tracks/check_line.hpp @@ -64,8 +64,7 @@ private: * quad and still considered to be able to cross it. */ static const int m_over_min_height = 4; public: - CheckLine(CheckManager *check_manager, const XMLNode &node, - unsigned int index); + CheckLine(const XMLNode &node, unsigned int index); virtual ~CheckLine(); virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx); virtual void reset(const Track &track); diff --git a/src/tracks/check_manager.cpp b/src/tracks/check_manager.cpp index c69876fea..487f66848 100644 --- a/src/tracks/check_manager.cpp +++ b/src/tracks/check_manager.cpp @@ -28,7 +28,11 @@ #include "tracks/check_structure.hpp" #include "tracks/track.hpp" -CheckManager::CheckManager(const XMLNode &node, Track *track) +CheckManager *CheckManager::m_check_manager = NULL; + +/** Loads all check structure informaiton from the specified xml file. + */ +void CheckManager::load(const XMLNode &node) { for(unsigned int i=0; igetName(); if(type=="check-line") { - CheckLine *cl = new CheckLine(this, *check_node, i); + CheckLine *cl = new CheckLine(*check_node, i); m_all_checks.push_back(cl); } // checkline else if(type=="check-lap") { - m_all_checks.push_back(new CheckLap(this, *check_node, i)); + m_all_checks.push_back(new CheckLap(*check_node, i)); } else if(type=="check-sphere") { - AmbientLightSphere *cs = new AmbientLightSphere(this, *check_node, + AmbientLightSphere *cs = new AmbientLightSphere(*check_node, i); m_all_checks.push_back(cs); } // checksphere @@ -78,15 +82,19 @@ CheckManager::CheckManager(const XMLNode &node, Track *track) } } -} // CheckManager +} // load // ---------------------------------------------------------------------------- +/** Private destructor (to make sure it is only called using the static + * destroy function). Frees all check structures. + */ CheckManager::~CheckManager() { for(unsigned int i=0; i +#include "utils/no_copy.hpp" + +#include #include +#include class XMLNode; class CheckStructure; @@ -30,22 +33,40 @@ class Track; * \brief Controls all checks structures of a track. * \ingroup tracks */ -class CheckManager +class CheckManager : public NoCopy { private: std::vector m_all_checks; + static CheckManager *m_check_manager; + /** Private constructor, to make sure it is only called via + * the static create function. */ + CheckManager() {m_all_checks.clear();}; + ~CheckManager(); public: - CheckManager(const XMLNode &node, Track *track); - ~CheckManager(); - void update(float dt); - void reset(const Track &track); - + void load(const XMLNode &node); + void update(float dt); + void reset(const Track &track); + // ------------------------------------------------------------------------ + /** Creates an instance of the check manager. */ + static void create() + { + assert(!m_check_manager); + m_check_manager = new CheckManager(); + } // create + // ------------------------------------------------------------------------ + /** Returns the instance of the check manager. */ + static CheckManager* get() { return m_check_manager; } + // ------------------------------------------------------------------------ + /** Destroys the check manager. */ + static void destroy() { delete m_check_manager; m_check_manager = NULL; } + // ------------------------------------------------------------------------ + /** Returns the number of check structures defined. */ int getCheckStructureCount() const { return m_all_checks.size(); } - + // ------------------------------------------------------------------------ /** Returns the nth. check structure. */ CheckStructure *getCheckStructure(unsigned int n) { - if (n >= m_all_checks.size()) return NULL; + assert(n < m_all_checks.size()); return m_all_checks[n]; } }; // CheckManager diff --git a/src/tracks/check_sphere.cpp b/src/tracks/check_sphere.cpp index 1b6799b12..4f4848a02 100644 --- a/src/tracks/check_sphere.cpp +++ b/src/tracks/check_sphere.cpp @@ -30,9 +30,8 @@ * resetting e.g. new lap counters. * \param node XML node containing the parameters for this checkline. */ -CheckSphere::CheckSphere(CheckManager *check_manager, const XMLNode &node, - unsigned int index) - : CheckStructure(check_manager, node, index) +CheckSphere::CheckSphere(const XMLNode &node, unsigned int index) + : CheckStructure(node, index) { m_radius2 = 1; diff --git a/src/tracks/check_sphere.hpp b/src/tracks/check_sphere.hpp index a00dcc415..3d4fa90e4 100644 --- a/src/tracks/check_sphere.hpp +++ b/src/tracks/check_sphere.hpp @@ -45,8 +45,7 @@ private: * This saves some computations. */ std::vector m_distance2; public: - CheckSphere(CheckManager *check_manager, const XMLNode &node, - unsigned int index); + CheckSphere(const XMLNode &node, unsigned int index); virtual ~CheckSphere() {}; virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int kart_id); diff --git a/src/tracks/check_structure.cpp b/src/tracks/check_structure.cpp index 98e88940b..f35a5a7f0 100644 --- a/src/tracks/check_structure.cpp +++ b/src/tracks/check_structure.cpp @@ -28,11 +28,9 @@ #include "tracks/check_manager.hpp" -CheckStructure::CheckStructure(CheckManager *check_manager, - const XMLNode &node, unsigned int index) +CheckStructure::CheckStructure(const XMLNode &node, unsigned int index) { m_index = index; - m_check_manager = check_manager; m_check_type = CT_NEW_LAP; // This structure is actually filled by the check manager (necessary @@ -115,7 +113,7 @@ void CheckStructure::update(float dt) // ---------------------------------------------------------------------------- /** Changes the status (active/inactive) of all check structures contained * in the index list indices. - * \param indices List of index of check structures in check_manager that + * \param indices List of index of check structures in the CheckManager that * are to be changed. * \param int kart_index For which the status should be changed. * \param change_state How to change the state (active, deactivate, toggle). @@ -131,7 +129,7 @@ void CheckStructure::changeStatus(const std::vector indices, for(unsigned int i=0; igetCheckStructure(indices[i]); + CheckManager::get()->getCheckStructure(indices[i]); if (cs == NULL) continue; switch(change_state) @@ -177,9 +175,9 @@ void CheckStructure::changeStatus(const std::vector indices, /* printf("--------\n"); - for (int n=0; ngetCheckStructureCount(); n++) + for (int n=0; ngetCheckStructureCount(); n++) { - CheckStructure *cs = m_check_manager->getCheckStructure(n); + CheckStructure *cs = CheckManager::get()->getCheckStructure(n); if (dynamic_cast(cs) != NULL) printf("Checkline %i (LAP) : %i\n", n, (int)cs->m_is_active[kart_index]); else diff --git a/src/tracks/check_structure.hpp b/src/tracks/check_structure.hpp index 99ae2f5b8..86137e188 100644 --- a/src/tracks/check_structure.hpp +++ b/src/tracks/check_structure.hpp @@ -73,9 +73,6 @@ protected: bool m_active_at_reset; private: - /** Stores a pointer to the check manager. */ - CheckManager *m_check_manager; - /** The type of this checkline. */ CheckType m_check_type; @@ -100,8 +97,7 @@ private: ChangeState change_state); public: - CheckStructure(CheckManager *check_manager, const XMLNode &node, - unsigned int index); + CheckStructure(const XMLNode &node, unsigned int index); virtual ~CheckStructure() {}; virtual void update(float dt); virtual void changeDebugColor(bool is_active) {} diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index 48788f04d..a546ce927 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -211,7 +211,7 @@ void QuadGraph::load(const std::string &filename) void QuadGraph::setChecklineRequirements(GraphNode* node, int latest_checkline) { Track* t = World::getWorld()->getTrack(); - CheckManager* cm = t->getCheckManager(); + CheckManager* cm = CheckManager::get(); assert(cm != NULL); // Find lapline diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index dcdd38fc3..4a24ae5d7 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -91,7 +91,6 @@ Track::Track(const std::string &filename) m_all_cached_meshes.clear(); m_is_arena = false; m_camera_far = 1000.0f; - m_check_manager = NULL; m_mini_map = NULL; m_sky_particles = NULL; m_sky_dx = 0.05f; @@ -121,8 +120,7 @@ Track::~Track() void Track::reset() { m_ambient_color = m_default_ambient_color; - if(m_check_manager) - m_check_manager->reset(*this); + CheckManager::get()->reset(*this); item_manager->reset(); m_track_object_manager->reset(); } // reset @@ -152,11 +150,7 @@ void Track::cleanup() m_all_emitters.clearAndDeleteAll(); - if(m_check_manager) - { - delete m_check_manager; - m_check_manager=NULL; - } + CheckManager::destroy(); delete m_track_object_manager; m_track_object_manager = NULL; @@ -197,7 +191,7 @@ void Track::cleanup() m_all_cached_meshes.clear(); QuadGraph::destroy(); - if(m_check_manager) delete m_check_manager; + if(m_mini_map) { assert(m_mini_map->getReferenceCount()==1); @@ -1050,8 +1044,7 @@ void Track::update(float dt) { m_animated_textures[i]->update(dt); } - if(m_check_manager) - m_check_manager->update(dt); + CheckManager::get()->update(dt); item_manager->update(dt); } // update @@ -1151,6 +1144,7 @@ void Track::loadTrackModel(World* parent, bool reverse_track, { reverse_track = false; } + CheckManager::create(); assert(m_all_cached_meshes.size()==0); if(UserConfigParams::logMemory()) { @@ -1315,7 +1309,7 @@ void Track::loadTrackModel(World* parent, bool reverse_track, } else if(name=="checks") { - m_check_manager = new CheckManager(*node, this); + CheckManager::get()->load(*node); } else if (name=="particle-emitter") { @@ -1549,7 +1543,8 @@ void Track::loadTrackModel(World* parent, bool reverse_track, // Only print warning if not in battle mode, since battle tracks don't have // any quads or check lines. - if(!m_check_manager && race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES) + if(CheckManager::get()->getCheckStructureCount()==0 && + race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES) { printf("WARNING: no check lines found in track '%s'.\n", m_ident.c_str()); @@ -1843,8 +1838,8 @@ std::vector< std::vector > Track::buildHeightMap() } // ---------------------------------------------------------------------------- - -core::vector3df Track::getSunRotation() +/** Returns the rotation of the sun. */ +const core::vector3df& Track::getSunRotation() { return m_sun->getRotation(); } diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 979b77e24..43dbfd52f 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -279,9 +279,6 @@ private: /** List of all bezier curves in the track - for e.g. camera, ... */ std::vector m_all_curves; - /** Checkline manager. */ - CheckManager *m_check_manager; - void loadTrackInfo(); void itemCommand(const Vec3 &xyz, Item::ItemType item_type, bool drop); @@ -312,7 +309,7 @@ public: void reset(); void adjustForFog(scene::ISceneNode *node); void adjustForFog(scene::IMesh* mesh, scene::ISceneNode* parent_scene_node); - + const core::vector3df& getSunRotation(); /** Sets the current ambient color for a kart with index k. */ void setAmbientColor(const video::SColor &color, unsigned int k); @@ -430,17 +427,13 @@ public: ParticleKind* getSkyParticles () { return m_sky_particles; } // ------------------------------------------------------------------------ bool isFogEnabled() const { return m_use_fog; } - - CheckManager* getCheckManager() { return m_check_manager; } - + // ------------------------------------------------------------------------ /** Whether this is an "internal" track. If so it won't be offered - * in the track seelction screen - */ + * in the track seelction screen. */ bool isInternal() const { return m_internal; } - - core::vector3df getSunRotation(); - - TrackObjectManager* getTrackObjectManager() { return m_track_object_manager; } + + // ------------------------------------------------------------------------ + TrackObjectManager* getTrackObjectManager() {return m_track_object_manager;} /** Get list of challenges placed on that world. Works only for overworld. */ const std::vector& getChallengeList() const From fcdf44c764441e08ba6288324ecc6539b09fc2b0 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 14 Feb 2012 20:51:29 +0000 Subject: [PATCH 55/68] 1) Fixed computing of checkling requirements to work properly with reverse tracks. Simplified code by moving some functionality from QuadGraph to CheckManager. 2) Added comments, renamed some functions to better indicate what they are doing. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10843 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/modes/linear_world.hpp | 2 +- src/modes/overworld.hpp | 2 +- src/modes/world.hpp | 2 +- src/tracks/check_manager.cpp | 38 +++++++++++++ src/tracks/check_manager.hpp | 9 ++-- src/tracks/quad_graph.cpp | 100 +++++++++++++++-------------------- src/tracks/quad_graph.hpp | 11 ++-- src/tracks/track.cpp | 4 +- 8 files changed, 96 insertions(+), 72 deletions(-) diff --git a/src/modes/linear_world.hpp b/src/modes/linear_world.hpp index 1b3c52e9d..ed885faf3 100644 --- a/src/modes/linear_world.hpp +++ b/src/modes/linear_world.hpp @@ -137,7 +137,7 @@ public: virtual bool haveBonusBoxes(){ return true; } // ------------------------------------------------------------------------ /** Override settings from base class */ - virtual bool computeChecklineRequirements() const { return true; } + virtual bool useChecklineRequirements() const { return true; } // ------------------------------------------------------------------------ /** Returns true if the kart is on a valid driveline quad. * \param kart_index Index of the kart. */ diff --git a/src/modes/overworld.hpp b/src/modes/overworld.hpp index 1b6c7422b..c8bf7e8ee 100644 --- a/src/modes/overworld.hpp +++ b/src/modes/overworld.hpp @@ -68,7 +68,7 @@ public: virtual void onFirePressed(Controller* who); // ------------------------------------------------------------------------ /** Override settings from base class */ - virtual bool computeChecklineRequirements() const { return false; } + virtual bool useChecklineRequirements() const { return false; } }; #endif diff --git a/src/modes/world.hpp b/src/modes/world.hpp index a211b298c..befa82896 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -279,7 +279,7 @@ public: /** Whether to compute checkline requirements for each world on the * quadgraph. Override to change value. */ - virtual bool computeChecklineRequirements() const { return false; } + virtual bool useChecklineRequirements() const { return false; } }; // World diff --git a/src/tracks/check_manager.cpp b/src/tracks/check_manager.cpp index 487f66848..1cf1fada0 100644 --- a/src/tracks/check_manager.cpp +++ b/src/tracks/check_manager.cpp @@ -118,3 +118,41 @@ void CheckManager::update(float dt) (*i)->update(dt); } // update +// ---------------------------------------------------------------------------- +/** Returns the index of the first check structures that triggers a new + * lap to be counted. It aborts if no lap structure is defined. + */ +unsigned int CheckManager::getLapLineIndex() const +{ + for (unsigned int i=0; i(c) != NULL) return i; + } + + fprintf(stderr, "Error, no lap line for track found, aborting.\n"); + exit(-1); +} // getLapLineIndex + +// ---------------------------------------------------------------------------- +/** Returns the check line index that is triggered when going from 'from' + * to 'to'. If no check line is triggered, -1 will be returned. + * \param from Coordinates to start from. + * \param to Coordinates to go to. + */ +int CheckManager::getChecklineTriggering(const Vec3 &from, + const Vec3 &to) const +{ + for (unsigned int i=0; i(c) != NULL) continue; + + if (c->isTriggered(from, to, 0 /* kart id */)) + return i; + } + return -1; +} // getChecklineTriggering \ No newline at end of file diff --git a/src/tracks/check_manager.hpp b/src/tracks/check_manager.hpp index 28eca79ad..a861be086 100644 --- a/src/tracks/check_manager.hpp +++ b/src/tracks/check_manager.hpp @@ -25,9 +25,10 @@ #include #include -class XMLNode; class CheckStructure; class Track; +class XMLNode; +class Vec3; /** * \brief Controls all checks structures of a track. @@ -46,6 +47,8 @@ public: void load(const XMLNode &node); void update(float dt); void reset(const Track &track); + unsigned int getLapLineIndex() const; + int getChecklineTriggering(const Vec3 &from, const Vec3 &to) const; // ------------------------------------------------------------------------ /** Creates an instance of the check manager. */ static void create() @@ -61,10 +64,10 @@ public: static void destroy() { delete m_check_manager; m_check_manager = NULL; } // ------------------------------------------------------------------------ /** Returns the number of check structures defined. */ - int getCheckStructureCount() const { return m_all_checks.size(); } + unsigned int getCheckStructureCount() const { return m_all_checks.size(); } // ------------------------------------------------------------------------ /** Returns the nth. check structure. */ - CheckStructure *getCheckStructure(unsigned int n) + CheckStructure *getCheckStructure(unsigned int n) const { assert(n < m_all_checks.size()); return m_all_checks[n]; diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index a546ce927..56adee3b3 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -183,13 +183,7 @@ void QuadGraph::load(const std::string &filename) delete xml; setDefaultSuccessors(); - - // The track exporter always exports quad 0 as first quad after (or at) - // the start line (start line is lower side of quad 0). In reverse mode - // the start quad is the predecessor of node 0. - unsigned int start_node = m_reverse ? m_all_nodes[0]->getSuccessor(0) - : 0; - computeDistanceFromStart(start_node, 0.0f); + computeDistanceFromStart(getStartNode(), 0.0f); // Define the track length as the maximum at the end of a quad // (i.e. distance_from_start + length till successor 0). @@ -204,55 +198,46 @@ void QuadGraph::load(const std::string &filename) } // load // ---------------------------------------------------------------------------- -/** - * Finds which checklines must be visited before driving on this quad - * (useful for rescue) - */ -void QuadGraph::setChecklineRequirements(GraphNode* node, int latest_checkline) +/** Returns the index of the first graph node (i.e. the graph node which + * will trigger a new lap when a kart first enters it). This is always + * 0 for normal direction (this is guaranteed by the track exporter), + * but in reverse mode (where node 0 is actually the end of the track) + * this is 0's successor. + */ +unsigned int QuadGraph::getStartNode() const { - Track* t = World::getWorld()->getTrack(); - CheckManager* cm = CheckManager::get(); - assert(cm != NULL); - - // Find lapline - if (latest_checkline == -1) - { - for (int i=0; igetCheckStructureCount(); i++) - { - CheckStructure* c = cm->getCheckStructure(i); - - if (dynamic_cast(c) != NULL) - { - latest_checkline = i; - break; - } - } - } - + return m_reverse ? m_all_nodes[0]->getSuccessor(0) + : 0; +} // getStartNode + +// ---------------------------------------------------------------------------- +void QuadGraph::computeChecklineRequirements() +{ + computeChecklineRequirements(m_all_nodes[0], + CheckManager::get()->getLapLineIndex()); +} // computeChecklineRequirements + +// ---------------------------------------------------------------------------- +/** Finds which checklines must be visited before driving on this quad + * (useful for rescue) + */ +void QuadGraph::computeChecklineRequirements(GraphNode* node, + int latest_checkline) +{ for (unsigned int n=0; ngetNumberOfSuccessors(); n++) { const int succ_id = node->getSuccessor(n); // warp-around if (succ_id == 0) break; - - int new_latest_checkline = latest_checkline; - - GraphNode* succ = m_all_nodes[succ_id]; - for (int i=0; igetCheckStructureCount(); i++) - { - CheckStructure* c = cm->getCheckStructure(i); - // skip lapline - if (dynamic_cast(c) != NULL) continue; - - if (c->isTriggered(node->getCenter(), succ->getCenter(), 0 /* kart id */)) - { - new_latest_checkline = i; - break; - } - } - + GraphNode* succ = m_all_nodes[succ_id]; + int new_latest_checkline = + CheckManager::get()->getChecklineTriggering(node->getCenter(), + succ->getCenter() ); + if(new_latest_checkline==-1) + new_latest_checkline = latest_checkline; + /* printf("Quad %i : checkline %i\n", succ_id, new_latest_checkline); @@ -266,9 +251,9 @@ void QuadGraph::setChecklineRequirements(GraphNode* node, int latest_checkline) if (new_latest_checkline != -1) succ->setChecklineRequirements(new_latest_checkline); - setChecklineRequirements(succ, new_latest_checkline); + computeChecklineRequirements(succ, new_latest_checkline); } -} +} // computeChecklineRequirements // ---------------------------------------------------------------------------- /** This function defines the "path-to-nodes" for each graph node that has @@ -334,13 +319,9 @@ void QuadGraph::setDefaultStartPositions(AlignedArray float sidewards_distance, float upwards_distance) const { - // In non-reverse mode: node 0 is the node on which the start line is. - // So get its predecessor (which is therefore just - // before the start line) to find the first quad - // to place karts on. - // In reverse mode, karts can start to placed on quad 0. - int current_node = m_reverse ? getNode(0).getIndex() - : getNode(0).getPredecessor(); + // We start just before the start node (which will trigger lap + // counting when reached). + int current_node = m_all_nodes[getStartNode()]->getPredecessor(); float distance_from_start = 0.1f+forwards_distance; @@ -585,6 +566,11 @@ void QuadGraph::getSuccessors(int node_number, } // getSuccessors // ---------------------------------------------------------------------------- +/** Recursively determines the distance the beginning (lower end) of the quads + * have from the start of the track. + * \param node The node index for which to set the distance from start. + * \param new_distance The new distance for the specified graph node. + */ void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance) { GraphNode *gn = m_all_nodes[node]; diff --git a/src/tracks/quad_graph.hpp b/src/tracks/quad_graph.hpp index badbe4d03..d0aaecf8a 100644 --- a/src/tracks/quad_graph.hpp +++ b/src/tracks/quad_graph.hpp @@ -79,7 +79,7 @@ private: bool m_reverse; void setDefaultSuccessors(); - void setChecklineRequirements(GraphNode* node, int latest_checkline); + void computeChecklineRequirements(GraphNode* node, int latest_checkline); void addSuccessor(unsigned int from, unsigned int to); void load (const std::string &filename); @@ -87,6 +87,7 @@ private: void createMesh(bool show_invisible=true, const video::SColor *track_color=NULL, const video::SColor *lap_color=NULL); + unsigned int getStartNode() const; QuadGraph (const std::string &quad_file_name, const std::string graph_file_name, const bool reverse); @@ -120,7 +121,8 @@ public: void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *out) const; void updateDistancesForAllSuccessors(unsigned int indx, float delta); void setupPaths(); - // ---------------------------------------------------------------------- + void computeChecklineRequirements(); +// ---------------------------------------------------------------------- /** Returns the one instance of this object. It is possible that there * is no instance created (e.g. in battle mode, since it doesn't have * a quad graph), so we don't assert that an instance exist, and we @@ -182,11 +184,6 @@ public: // ---------------------------------------------------------------------- /** Returns true if the graph is to be reversed. */ bool isReverse() const {return m_reverse; } - // ---------------------------------------------------------------------- - void setChecklineRequirements() - { - setChecklineRequirements(m_all_nodes[0], -1); - } }; // QuadGraph diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 4a24ae5d7..61f7e1445 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1557,9 +1557,9 @@ void Track::loadTrackModel(World* parent, bool reverse_track, irr_driver->getSceneManager()->getMeshCache()->getMeshCount(), irr_driver->getVideoDriver()->getTextureCount()); - if (World::getWorld()->computeChecklineRequirements()) + if (World::getWorld()->useChecklineRequirements()) { - QuadGraph::get()->setChecklineRequirements(); + QuadGraph::get()->computeChecklineRequirements(); } } // loadTrackModel From 8105b6ac0c79918d63ad179e581e252688734ec1 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 14 Feb 2012 21:15:37 +0000 Subject: [PATCH 56/68] Fixed end camera handling in reverse mode. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10844 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/graphics/camera.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index cdf0d4358..22ad4c6d4 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -114,7 +114,12 @@ void Camera::readEndCamera(const XMLNode &root) m_end_cameras.clear(); for(unsigned int i=0; iisReverse()) + index = root.getNumNodes() - 1 - i; + const XMLNode *node = root.getNode(index); EndCameraInformation eci; if(!eci.readXML(*node)) continue; m_end_cameras.push_back(eci); From e13a7078d80e0a86904b3eb9d0afdf64cdcb2d6d Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 14 Feb 2012 23:25:43 +0000 Subject: [PATCH 57/68] Fixed warnings being printed at race start when using 0 lap races. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10845 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/modes/linear_world.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 1be69456a..07874856e 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -496,12 +496,10 @@ float LinearWorld::estimateFinishTimeForKart(Kart* kart) // In case that a kart is rescued behind start line, or ... if(distance_covered<0) distance_covered =1.0f; - const float full_distance = race_manager->getNumLaps() - * m_track->getTrackLength(); - const float average_speed = distance_covered/getTime(); - - // Finish time is the time needed for the whole race with - // the average speed computed above. + float full_distance = race_manager->getNumLaps() + * m_track->getTrackLength(); + if(full_distance == 0) + full_distance = 1; // For 0 lap races avoid warning below #ifdef DEBUG if(full_distance < distance_covered) { @@ -510,9 +508,17 @@ float LinearWorld::estimateFinishTimeForKart(Kart* kart) printf("%f < %f\n", full_distance, distance_covered); } #endif + // Avoid potential problems (floating point issues, coding bug?) if a + // kart has driven more than the full distance, but not finished: + // Return the current time plus initial position to spread arrival + // times a bit. This code should generally not be used at all, it's + // just here to avoid invalid finishing times. if(full_distance < distance_covered) return getTime() + kart->getInitialPosition(); + // Finish time is the time needed for the whole race with + // the computed average speed computed. + const float average_speed = distance_covered/getTime(); return getTime() + (full_distance - distance_covered) / average_speed; } // estimateFinishTimeForKart From 4967ca992af54f573e6f32a97bd74af2e530d2c4 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 14 Feb 2012 23:27:23 +0000 Subject: [PATCH 58/68] Fixed one-frame jump when switching end cameras (esp. to static camera). Main reason was that setPosition does not update the absolutePosition of the camera, but also that the camera position got switched without applying all settings (like zoom). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10846 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/graphics/camera.cpp | 42 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 22ad4c6d4..9bb6189a8 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -510,6 +510,25 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle, */ void Camera::handleEndCamera(float dt) { + // First test if the kart is close enough to the next end camera, and + // if so activate it. + if( m_end_cameras.size()>0 && + m_end_cameras[m_next_end_camera].isReached(m_kart->getXYZ())) + { + m_current_end_camera = m_next_end_camera; + if(m_end_cameras[m_current_end_camera].m_type + ==EndCameraInformation::EC_STATIC_FOLLOW_KART) + { + m_camera->setPosition( + m_end_cameras[m_current_end_camera].m_position.toIrrVector() + ); + } + m_camera->setFOV(m_fov); + m_next_end_camera++; + if(m_next_end_camera>=(unsigned)m_end_cameras.size()) + m_next_end_camera = 0; + } + EndCameraInformation::EndCameraType info = m_end_cameras.size()==0 ? EndCameraInformation::EC_AHEAD_OF_KART : m_end_cameras[m_current_end_camera].m_type; @@ -518,7 +537,11 @@ void Camera::handleEndCamera(float dt) { case EndCameraInformation::EC_STATIC_FOLLOW_KART: { - const core::vector3df &cp = m_camera->getAbsolutePosition(); + // Since the camera has no parents, we can use the relative + // position here (otherwise we need to call updateAbsolutePosition + // after changing the relative position in order to get the right + // position here). + const core::vector3df &cp = m_camera->getPosition(); const Vec3 &kp = m_kart->getXYZ(); // Estimate the fov, assuming that the vector from the camera to // the kart and the kart length are orthogonal to each other @@ -546,22 +569,7 @@ void Camera::handleEndCamera(float dt) default: break; } // switch - // Now test if the kart is close enough to the next end camera, and - // if so activate it. - if( m_end_cameras.size()>0 && - m_end_cameras[m_next_end_camera].isReached(m_kart->getXYZ())) - { - m_current_end_camera = m_next_end_camera; - if(m_end_cameras[m_current_end_camera].m_type - ==EndCameraInformation::EC_STATIC_FOLLOW_KART) - m_camera->setPosition( - m_end_cameras[m_current_end_camera].m_position.toIrrVector() - ); - m_camera->setFOV(m_fov); - m_next_end_camera++; - if(m_next_end_camera>=(unsigned)m_end_cameras.size()) m_next_end_camera = 0; - } -} // checkForNextEndCamera +} // handleEndCamera // ---------------------------------------------------------------------------- /** Sets viewport etc. for this camera. Called from irr_driver just before From 94be2cfec2d2eb391a820725d0b01e115d259971 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 15 Feb 2012 05:23:21 +0000 Subject: [PATCH 59/68] Automatically switch to camera 0 when the lap line is crossed. This improved handling of end cameras for reverse mode (otherwise one additional end camera would need to be defined to be used just when the lap line is crossed). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10850 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/graphics/camera.cpp | 11 ++++------- src/karts/controller/end_controller.cpp | 12 ++++++++++++ src/karts/controller/end_controller.hpp | 1 + src/modes/linear_world.cpp | 13 +++++++++---- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 9bb6189a8..62550fcb5 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -225,12 +225,8 @@ void Camera::setMode(Mode mode) { m_next_end_camera = m_end_cameras.size()>1 ? 1 : 0; m_current_end_camera = 0; - if(m_end_cameras.size()>0 && - m_end_cameras[0].m_type==EndCameraInformation::EC_STATIC_FOLLOW_KART) - { - m_camera->setPosition(m_end_cameras[0].m_position.toIrrVector()); - m_camera->setTarget(m_kart->getXYZ().toIrrVector()); - } + m_camera->setFOV(m_fov); + handleEndCamera(0); } // mode==CM_FINAL m_mode = mode; @@ -496,7 +492,8 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle, if (race_manager->getNumLocalPlayers() < 2) { - sfx_manager->positionListener(m_camera->getPosition(), wanted_target - m_camera->getPosition()); + sfx_manager->positionListener(m_camera->getPosition(), + wanted_target - m_camera->getPosition()); } } diff --git a/src/karts/controller/end_controller.cpp b/src/karts/controller/end_controller.cpp index 6f6e93232..2310bf527 100644 --- a/src/karts/controller/end_controller.cpp +++ b/src/karts/controller/end_controller.cpp @@ -134,6 +134,18 @@ void EndController::reset() } } // reset +//----------------------------------------------------------------------------- +/** Callback when a new lap is triggered. It is used to switch to the first + * end camera (which is esp. useful in fixing up end cameras in reverse mode, + * since otherwise the switch to the first end camera usually happens way too + * late) + */ +void EndController::newLap(int lap) +{ + // This will implicitely trigger setting the first end camera to be active. + m_kart->getCamera()->setMode(Camera::CM_FINAL); +} // newLap + //----------------------------------------------------------------------------- /** The end controller must forward 'fire' presses to the race gui. */ diff --git a/src/karts/controller/end_controller.hpp b/src/karts/controller/end_controller.hpp index 63f1d88d5..6450413bf 100644 --- a/src/karts/controller/end_controller.hpp +++ b/src/karts/controller/end_controller.hpp @@ -86,6 +86,7 @@ public: * to the right player. */ virtual bool isPlayerController () const {return m_player!=NULL;} virtual void action (PlayerAction action, int value); + virtual void newLap (int lap); }; // EndKart diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 07874856e..ceeacd0cf 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -216,10 +216,15 @@ void LinearWorld::newLap(unsigned int kart_index) KartInfo &kart_info = m_kart_info[kart_index]; Kart *kart = m_karts[kart_index]; - // Don't do anything if a kart that has already finished the race - // crosses the start line again. This avoids 'fastest lap' messages - // if the end controller does a fastest lap. - if(kart->hasFinishedRace()) return; + // Only update the kart controller if a kart that has already finished + // the race crosses the start line again. This avoids 'fastest lap' + // messages if the end controller does a fastest lap, but especially + // allows the end controller to switch end cameras + if(kart->hasFinishedRace()) + { + kart->getController()->newLap(kart_info.m_race_lap); + return; + } const int lap_count = race_manager->getNumLaps(); From 15445f182cdd513d91cd2d01d2980ed9945c52fb Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 15 Feb 2012 05:27:27 +0000 Subject: [PATCH 60/68] Adjust start position of camera (for initial camera movement) properly, which especially fixes its position in reverse mode. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10851 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/graphics/camera.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 62550fcb5..97130b037 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -256,8 +256,9 @@ void Camera::reset() */ void Camera::setInitialTransform() { - m_camera->setPosition( m_kart->getXYZ().toIrrVector() - + core::vector3df(0, 25, -50) ); + Vec3 start_offset(0, 25, -50); + Vec3 xx = m_kart->getTrans()(start_offset); + m_camera->setPosition( xx.toIrrVector()); // Reset the target from the previous target (in case of a restart // of a race) - otherwise the camera will initially point in the wrong // direction till smoothMoveCamera has corrected this. Setting target From d76777f76507ba4352507005e38997c9c1465d1c Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 15 Feb 2012 20:54:11 +0000 Subject: [PATCH 61/68] Fixed crash with end controller. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10852 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/controller/end_controller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/karts/controller/end_controller.cpp b/src/karts/controller/end_controller.cpp index 2310bf527..d1295a04b 100644 --- a/src/karts/controller/end_controller.cpp +++ b/src/karts/controller/end_controller.cpp @@ -143,7 +143,8 @@ void EndController::reset() void EndController::newLap(int lap) { // This will implicitely trigger setting the first end camera to be active. - m_kart->getCamera()->setMode(Camera::CM_FINAL); + if(m_kart->getCamera()) + m_kart->getCamera()->setMode(Camera::CM_FINAL); } // newLap //----------------------------------------------------------------------------- From 5e2dcb7963b8c7f862d16ccc513ea9998c5e371d Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 15 Feb 2012 20:55:36 +0000 Subject: [PATCH 62/68] Fixed crash when using reverse in tracks with short cuts that are hidden for the AI. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10853 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/controller/ai_base_controller.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/karts/controller/ai_base_controller.cpp b/src/karts/controller/ai_base_controller.cpp index 11b4cba9b..62963abc2 100644 --- a/src/karts/controller/ai_base_controller.cpp +++ b/src/karts/controller/ai_base_controller.cpp @@ -78,6 +78,14 @@ void AIBaseController::computePath() next.clear(); // Get all successors the AI is allowed to take. QuadGraph::get()->getSuccessors(i, next, /*for_ai*/true); + // In case of short cuts hidden for the AI it can be that a node + // might not have a successor (since the first and last edge of + // a hidden shortcut is ignored). Since in the case that the AI + // ends up on a short cut (e.g. by accident) and doesn't have an + // allowed way to drive, it should still be able to drive, so add + // the non-AI successors of that node in this case. + if(next.size()==0) + QuadGraph::get()->getSuccessors(i, next, /*for_ai*/false); // For now pick one part on random, which is not adjusted during the // race. Long term statistics might be gathered to determine the // best way, potentially depending on race position etc. From 5d956568b9e00d53bbcc164aa79c918cd286bdf7 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 15 Feb 2012 23:59:05 +0000 Subject: [PATCH 64/68] Fixed crash (which atm only happens with reverse mode, when the cow in farm is inivisible). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10857 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/graphics/lod_node.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graphics/lod_node.cpp b/src/graphics/lod_node.cpp index fe7cdf309..80dc128a2 100644 --- a/src/graphics/lod_node.cpp +++ b/src/graphics/lod_node.cpp @@ -172,6 +172,7 @@ void LODNode::OnRegisterSceneNode() { scene::IMeshBuffer* mb = mesh->getMeshBuffer(n); video::ITexture* t = mb->getMaterial().getTexture(0); + if(!t) continue; Material* m = material_manager->getMaterialFor(t, mb); if (m != NULL) { From 9b07ffe94fc9fc35d479489c401223403665f018 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 16 Feb 2012 05:27:52 +0000 Subject: [PATCH 65/68] Removed debug print. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10863 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/states_screens/dialogs/track_info_dialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/states_screens/dialogs/track_info_dialog.cpp b/src/states_screens/dialogs/track_info_dialog.cpp index 7e0fe45d5..2b4c92053 100644 --- a/src/states_screens/dialogs/track_info_dialog.cpp +++ b/src/states_screens/dialogs/track_info_dialog.cpp @@ -240,7 +240,6 @@ void TrackInfoDialog::onEnterPressedInternal() const bool reverse_track = m_checkbox == NULL ? false : m_checkbox->getState(); race_manager->setReverseTrack(reverse_track); - printf("Reverse: %d\n", reverse_track); std::string track_ident = m_track_ident; ModalDialog::dismiss(); race_manager->startSingleRace(track_ident, num_laps); From d1540ae903e85b5413b3aa6879e047e6672092b3 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 16 Feb 2012 05:33:31 +0000 Subject: [PATCH 66/68] Fixed missing screenshot. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10864 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/gui/track_info_dialog.stkgui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/gui/track_info_dialog.stkgui b/data/gui/track_info_dialog.stkgui index 51d30cb08..2f0444e19 100644 --- a/data/gui/track_info_dialog.stkgui +++ b/data/gui/track_info_dialog.stkgui @@ -43,7 +43,7 @@
- +
From 902ff01d3c464ed71b0d036aac6e2af34da347e7 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 16 Feb 2012 05:41:33 +0000 Subject: [PATCH 67/68] Remove 'reverse' checkbox in track info when the track does not support reverse driving. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10865 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/gui/track_info_dialog.stkgui | 2 +- src/states_screens/dialogs/track_info_dialog.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/data/gui/track_info_dialog.stkgui b/data/gui/track_info_dialog.stkgui index 2f0444e19..dc7fa27f8 100644 --- a/data/gui/track_info_dialog.stkgui +++ b/data/gui/track_info_dialog.stkgui @@ -49,7 +49,7 @@ -
diff --git a/src/states_screens/dialogs/track_info_dialog.cpp b/src/states_screens/dialogs/track_info_dialog.cpp index 2b4c92053..da20eb7cf 100644 --- a/src/states_screens/dialogs/track_info_dialog.cpp +++ b/src/states_screens/dialogs/track_info_dialog.cpp @@ -125,6 +125,8 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin } else { + getWidget("reverse")->setVisible(false); + getWidget("reverse-text")->setVisible(false); m_checkbox = NULL; race_manager->setReverseTrack(false); } From e57c34dc9cd112eb8306ea98452d858482d751e3 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 16 Feb 2012 10:20:26 +0000 Subject: [PATCH 68/68] Made 'reversible' the default for all tracks, removed unnecessary reverse=true from track.xml files. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10866 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/tracks/track.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 6127e2afb..3bc51859a 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -86,7 +86,7 @@ Track::Track(const std::string &filename) m_track_mesh = NULL; m_gfx_effect_mesh = NULL; m_internal = false; - m_reverse_available = false; + m_reverse_available = true; m_all_nodes.clear(); m_all_cached_meshes.clear(); m_is_arena = false;