Merged the switch_coordinate_system branch with trunk. This means

that now all coordinate systems are y up, z forwards - including
the file format. For now only one track has been ported, the
rest will follow shortly.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@4985 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-03-12 02:16:11 +00:00
commit d50bd9dbe6
52 changed files with 745 additions and 781 deletions

View File

@ -2,11 +2,32 @@
<?xml version="1.0"?>
<config>
<!-- Minimum and maximum kart versions that can be used by this binary.
Older version will be ignored. -->
<kart-version min="2" max="2"/>
<!-- Minimum and maxium track versions that be be read by this binary.
Older versions will be ignored. -->
<track-version min="2" max="2"/>
<!-- Maximum number of karts to be used at the same time. This limit
can easily be increased, but some tracks might not have valid start
positions for those additional karts. -->
<max-karts value="8"/>
<!--
<Scores =point="10 8 6 5 4 3 2 1"''>
grid-order="1"
title-music="main_theme.music"
mainmenu-background="st_title_screen.rgb st_title_screen2.rgb"
menu-background="menu_background.rgb menu_background2.rgb"
max-history="10000"
max-skidmarks="100"
skid-fadeout-time="60"
near-ground="2"
delay-finish-time="4"
music-credit-time="10"
final-camera-time="1.5"
-->
<!-- STK PARAMETERS
min-kart-version and max-kart-version are the the minimum and maximum .kart
files supported. Older/newer files are ignored.
min-track-version and max-track-version are the minimum and maximum .track
files supported, older/newer files are ignored.
@ -34,10 +55,10 @@ final-camera-time is the time for the final camera to reach it's destination
-->
<stk-parameters
min-kart-version="1"
max-kart-version="1"
min-track-version="1"
max-track-version="1"
min-kart-version="2"
max-kart-version="2"
min-track-version="2"
max-track-version="2"
max-karts="8"
scores="10 8 6 5 4 3 2 1"
grid-order="1"
@ -158,7 +179,7 @@ a hit kart receives depends on the orientation - if a kart is pushed
in the direction it is driving, it will be more (no friction from tires),
while when pushed to the side, hardly anything happens.
z-rescue-offset is the z-axis offset when kart is being put back on track
vert-rescue-offset is the z-axis offset when kart is being put back on track
after being rescued, it's a fraction of kart height
gear-switch-ratio defines at what ratio of the maximum speed what gear is
@ -189,7 +210,7 @@ rubber-band-duration is the duration a rubber band acts.
time-full-steer-ai="0.1"
corn-f ="4"
corn-r="4"
gravity-center-shift="0 0 0.3"
gravity-center-shift="0 0.3 0"
nitro-power-boost="3"
skid-increase="1.05"
@ -223,11 +244,11 @@ rubber-band-duration is the duration a rubber band acts.
suspension-travel-cm="19"
jump-velocity="3.0"
collision-side-impulse="0"
z-rescue-offset="0.0"
wheel-front-right="0.38 0.6 0"
wheel-front-left="-0.38 0.6 0"
wheel-rear-right="0.38 -0.6 0"
wheel-rear-left="-0.38 -0.6 0"
vert-rescue-offset="0.0"
wheel-front-right="0.38 0 0.6"
wheel-front-left="-0.38 0 0.6"
wheel-rear-right="0.38 0 -0.6"
wheel-rear-left="-0.38 0 -0.6"
gear-switch-ratio="0.25 0.7 1.0"
gear-power-increase="2.2 1.7 1.3"
upright-tolerance="0.2"

View File

@ -25,3 +25,28 @@ cp $LOCATION/src/BulletDynamics/Vehicle/*.cpp src/BulletDynamics/Vehicl
cp $LOCATION/Demos/OpenGL/*.h Demos/OpenGL
cp $LOCATION/Demos/OpenGL/*.cpp Demos/OpenGL
echo "REMEMBER to patch this new bullet version:"
echo "1) btDiscreteDynamicsWorld.cpp:
--- BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp (revision 4812)
+++ BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp (working copy)
@@ -262,7 +262,12 @@
for (int v=0;v<m_vehicles[i]->getNumWheels();v++)
{
//synchronize the wheels with the (interpolated) chassis worldtransform
+ // updateWheelTransform resets m_isInContact to false. Since
+ // this field is needed in STK, we save it here and restore
+ // its value after the call to updateWheelTransform.
+ bool contact = m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact;
m_vehicles[i]->updateWheelTransform(v,true);
+ m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact = contact;
}
}
}
"
echo "2) btRaycastVehicle.cpp
From:
rel_pos[2] *= wheelInfo.m_rollInfluence;
to
rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
"

View File

@ -262,7 +262,12 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
for (int v=0;v<m_vehicles[i]->getNumWheels();v++)
{
//synchronize the wheels with the (interpolated) chassis worldtransform
// updateWheelTransform resets m_isInContact to false. Since
// this field is needed in STK, we save it here and restore
// its value after the call to updateWheelTransform.
bool contact = m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact;
m_vehicles[i]->updateWheelTransform(v,true);
m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact = contact;
}
}
}

View File

@ -690,7 +690,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
rel_pos[2] *= wheelInfo.m_rollInfluence;
rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
m_chassisBody->applyImpulse(sideImp,rel_pos);
//apply friction impulse on the ground

View File

@ -232,7 +232,6 @@ namespace UserConfigParams
// ---- Debug
PARAM_PREFIX BoolUserConfigParam m_gamepad_debug PARAM_DEFAULT( BoolUserConfigParam(false, "gamepad_debug") );
PARAM_PREFIX IntUserConfigParam m_track_debug PARAM_DEFAULT( IntUserConfigParam(false, "track_debug") );
PARAM_PREFIX bool m_bullet_debug PARAM_DEFAULT( false );
PARAM_PREFIX bool m_print_kart_sizes PARAM_DEFAULT( false );
// ---- Networking

View File

@ -20,6 +20,8 @@
#include "graphics/camera.hpp"
#include "math.h"
#include "audio/sound_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
@ -48,7 +50,7 @@ Camera::Camera(int camera_index, const Kart* kart)
m_position_speed = 8.0f;
m_target_speed = 10.0f;
m_rotation_range = 0.4f;
reset();
} // Camera
// ----------------------------------------------------------------------------
@ -169,6 +171,7 @@ Camera::Mode Camera::getMode()
void Camera::reset()
{
setMode(CM_NORMAL);
setInitialTransform();
} // reset
//-----------------------------------------------------------------------------
@ -177,7 +180,9 @@ void Camera::reset()
*/
void Camera::setInitialTransform()
{
m_camera->setPosition( m_kart->getXYZ().toIrrVector() - core::vector3df(0, -25, 50) );
m_camera->setPosition( m_kart->getXYZ().toIrrVector()
+ core::vector3df(0, 25, -50) );
m_camera->setRotation(core::vector3df(0, 0, 0));
m_camera->setRotation( core::vector3df( 0.0f, 0.0f, 0.0f ) );
} // setInitialTransform
@ -206,7 +211,7 @@ void Camera::smoothMoveCamera(float dt, const Vec3 &wanted_position,
// high above the kart straight down.
#undef DEBUG_CAMERA
#ifdef DEBUG_CAMERA
core::vector3df xyz = RaceManager::getKart(0)->getXYZ().toIrrVector();
core::vector3df xyz = m_kart->getXYZ().toIrrVector();
m_camera->setTarget(xyz);
xyz.Y = xyz.Y+30;
m_camera->setPosition(xyz);
@ -225,16 +230,21 @@ void Camera::computeNormalCameraPosition(Vec3 *wanted_position,
Vec3 *wanted_target)
{
*wanted_target = m_kart->getXYZ();
wanted_target->setZ(wanted_target->getZ()+ 0.75f);
wanted_target->setY(wanted_target->getY()+ 0.75f);
// This first line moves the camera around behind the kart, pointing it
// towards where the kart is turning (and turning even more while skidding).
float steering = m_kart->getSteerPercent() * (1.0f + (m_kart->getSkidding() - 1.0f)/2.3f ); // dampen skidding effect
float dampened_steer = fabsf(steering) * steering; // quadratically to dampen small variations (but keep sign)
float angle_around = m_kart->getHPR().getX() + m_rotation_range * dampened_steer * 0.5f;
float angle_up = m_kart->getHPR().getY() - 30.0f*DEGREE_TO_RAD;
wanted_position->setX( sin(angle_around));
wanted_position->setY(-cos(angle_around));
wanted_position->setZ(-sin(angle_up) );
// The skidding effect is dampened.
float steering = m_kart->getSteerPercent()
* (1.0f + (m_kart->getSkidding() - 1.0f)/2.3f );
// quadratically to dampen small variations (but keep sign)
float dampened_steer = fabsf(steering) * steering;
float angle_around = m_kart->getHeading()
+ m_rotation_range * dampened_steer * 0.5f;
float angle_up = m_kart->getPitch() + 30.0f*DEGREE_TO_RAD;
wanted_position->setX(-sin(angle_around));
wanted_position->setY( sin(angle_up) );
wanted_position->setZ(-cos(angle_around));
*wanted_position *= m_distance;
*wanted_position += *wanted_target;
} // computeNormalCameraPosition
@ -247,7 +257,6 @@ void Camera::update(float dt)
{
Vec3 wanted_position;
Vec3 wanted_target = m_kart->getXYZ();
// Each case should set wanted_position and wanted_target according to
// what is needed for that mode. Yes, there is a lot of duplicate code
// but it is (IMHO) much easier to follow this way.
@ -261,12 +270,14 @@ void Camera::update(float dt)
}
case CM_REVERSE: // Same as CM_NORMAL except it looks backwards
{
wanted_target.setZ(wanted_target.getZ()+ 0.75f);
float angle_around = m_kart->getHPR().getX() - m_rotation_range * m_kart->getSteerPercent() * m_kart->getSkidding();
float angle_up = m_kart->getHPR().getY() + 30.0f*DEGREE_TO_RAD;
wanted_position.setX(-sin(angle_around));
wanted_position.setY( cos(angle_around));
wanted_position.setZ( sin(angle_up) );
wanted_target.setY(wanted_target.getY()+ 0.75f);
float angle_around = m_kart->getHeading()
+ m_rotation_range * m_kart->getSteerPercent()
* m_kart->getSkidding();
float angle_up = m_kart->getPitch() + 30.0f*DEGREE_TO_RAD;
wanted_position.setX( sin(angle_around));
wanted_position.setY( sin(angle_up) );
wanted_position.setZ( cos(angle_around));
wanted_position *= m_distance * 2.0f;
wanted_position += wanted_target;
smoothMoveCamera(dt, wanted_position, wanted_target);
@ -276,12 +287,15 @@ void Camera::update(float dt)
}
case CM_CLOSEUP: // Lower to the ground and closer to the kart
{
wanted_target.setZ(wanted_target.getZ()+0.75f);
float angle_around = m_kart->getHPR().getX() + m_rotation_range * m_kart->getSteerPercent() * m_kart->getSkidding();
float angle_up = m_kart->getHPR().getY() - 20.0f*DEGREE_TO_RAD;
wanted_target.setY(wanted_target.getY()+0.75f);
float angle_around = m_kart->getHeading()
+ m_rotation_range * m_kart->getSteerPercent()
* m_kart->getSkidding();
float angle_up = m_kart->getPitch()
- 20.0f*DEGREE_TO_RAD;
wanted_position.setX( sin(angle_around));
wanted_position.setY(-cos(angle_around));
wanted_position.setZ(-sin(angle_up) );
wanted_position.setY(-sin(angle_up) );
wanted_position.setZ(-cos(angle_around));
wanted_position *= m_distance * 0.5f;
wanted_position += wanted_target;
smoothMoveCamera(dt, wanted_position, wanted_target);
@ -294,11 +308,11 @@ void Camera::update(float dt)
wanted_target = kart->getXYZ().toIrrVector();
// Follows the leader kart, higher off of the ground, further from the kart,
// and turns in the opposite direction from the kart for a nice effect. :)
float angle_around = kart->getHPR().getX();
float angle_up = kart->getHPR().getY() + 40.0f*DEGREE_TO_RAD;
float angle_around = kart->getHeading();
float angle_up = kart->getPitch() + 40.0f*DEGREE_TO_RAD;
wanted_position.setX(sin(angle_around));
wanted_position.setY(cos(angle_around));
wanted_position.setZ(sin(angle_up) );
wanted_position.setY(sin(angle_up) );
wanted_position.setZ(cos(angle_around));
wanted_position *= m_distance * 2.0f;
wanted_position += wanted_target;
smoothMoveCamera(dt, wanted_position, wanted_target);

View File

@ -411,8 +411,9 @@ void IrrDriver::setAllMaterialFlags(scene::IAnimatedMesh *mesh) const
for(unsigned int j=0; j<video::MATERIAL_MAX_TEXTURES; j++)
{
video::ITexture* t=irr_material.getTexture(j);
if (!t) material_manager->setAllFlatMaterialFlags(mb);
else material_manager->setAllMaterialFlags(t, mb);
//if (!t) material_manager->setAllFlatMaterialFlags(mb);
//else material_manager->setAllMaterialFlags(t, mb);
if(t) material_manager->setAllMaterialFlags(t, mb);
} // for j<MATERIAL_MAX_TEXTURES
material_manager->setAllUntexturedMaterialFlags(mb);
@ -766,7 +767,7 @@ void IrrDriver::update(float dt)
const bool inRace = world!=NULL;
// With bullet debug view we have to clear the back buffer, but
// that's not necessary for non-debug
bool back_buffer_clear = inRace && UserConfigParams::m_bullet_debug;
bool back_buffer_clear = inRace && world->getPhysics()->isDebug();
m_device->getVideoDriver()->beginScene(back_buffer_clear,
true, video::SColor(255,100,101,140));
@ -795,9 +796,11 @@ void IrrDriver::update(float dt)
m_scene_manager->drawAll();
// Note that drawAll must be called before rendering
// the bullet debug view, since otherwise the camera
// is not set up properly.
if (UserConfigParams::m_bullet_debug)
World::getWorld()->getPhysics()->draw();
// is not set up properly. This is only used for
// the bullet debug view.
#ifdef DEBUG
World::getWorld()->getPhysics()->draw();
#endif
} // if kart->Camera
} // for i<world->getNumKarts()
// To draw the race gui we set the viewport back to the full

View File

@ -36,8 +36,8 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
for(unsigned int j=0; j<mb->getIndexCount(); j+=1) {
int indx=mbIndices[j];
Vec3 c(mbVertices[indx].Pos.X,
mbVertices[indx].Pos.Z,
mbVertices[indx].Pos.Y );
mbVertices[indx].Pos.Y,
mbVertices[indx].Pos.Z );
min->min(c);
max->max(c);
} // for j

View File

@ -47,7 +47,6 @@ SlipStream::SlipStream(Kart* kart) : MovingTexture(0, 0), m_kart(kart)
m_node = irr_driver->addMesh(m_mesh);
//m_node->setParent(m_kart->getNode());
m_node->setPosition(core::vector3df(0,
// 0*0.25f,
0*0.25f+2.5,
m_kart->getKartLength()) );
setTextureMatrix(&(m_node->getMaterial(0).getTextureMatrix(0)));

View File

@ -105,7 +105,6 @@ void InputManager::handleStaticAction(int key, int value)
{
Kart* kart = world->getLocalPlayerKart(0);
kart->setPowerup(POWERUP_BUBBLEGUM, 10000);
projectile_manager->newExplosion(Vec3(0, 8, 0.5));
}
break;
case KEY_F2:
@ -129,16 +128,6 @@ void InputManager::handleStaticAction(int key, int value)
kart->setPowerup(POWERUP_SWITCH, 10000);
}
break;
case KEY_F11:
if(value && control_is_pressed)
{
UserConfigParams::m_bullet_debug = !UserConfigParams::m_bullet_debug;
if(UserConfigParams::m_bullet_debug)
world->getPhysics()->activateDebug();
else
world->getPhysics()->deactivateDebug();
}
break;
case KEY_F5:
if (race_manager->getNumPlayers() ==1 )
{
@ -159,6 +148,12 @@ void InputManager::handleStaticAction(int key, int value)
Kart* kart = world->getLocalPlayerKart(0);
kart->setPowerup(POWERUP_ZIPPER, 10000);
}
case KEY_F11:
if(value && control_is_pressed)
{
world->getPhysics()->nextDebugMode();
}
break;
#endif
case KEY_F12:
UserConfigParams::m_display_fps = !UserConfigParams::m_display_fps;

View File

@ -47,16 +47,16 @@ Bowling::Bowling(Kart *kart) : Flyable(kart, POWERUP_BOWLING, 50.0f /* mass */)
if(m_speed < min_speed) m_speed = min_speed;
}
createPhysics(y_offset, btVector3(0.0f, m_speed*2, 0.0f),
createPhysics(y_offset, btVector3(0.0f, 0.0f, m_speed*2),
new btSphereShape(0.5f*m_extend.getY()),
-70.0f /*gravity*/,
true /*rotates*/);
// Even if the ball is fired backwards, m_speed must be positive,
// otherwise the ball can start to vibrate when energy is added.
m_speed = fabsf(m_speed);
// Do not adjust the z velociy depending on height above terrain, since
// Do not adjust the up velociy depending on height above terrain, since
// this would disable gravity.
setAdjustZVelocity(false);
setAdjustUpVelocity(false);
// unset no_contact_response flags, so that the ball
// will bounce off the track
@ -92,7 +92,7 @@ void Bowling::update(float dt)
{
Flyable::update(dt);
const Kart *kart=0;
btVector3 direction;
Vec3 direction;
float minDistance;
getClosestKart(&kart, &minDistance, &direction);
if(kart && minDistance<m_st_max_distance_squared) // move bowling towards kart
@ -112,7 +112,7 @@ void Bowling::update(float dt)
// speed, which causes the speed to increase, which in turn causes
// the ball to fly higher and higher.
btTransform trans = getTrans();
float hat = trans.getOrigin().getZ();
float hat = trans.getOrigin().getY();
btVector3 v = m_body->getLinearVelocity();
float vlen = v.length2();
if (hat<= m_max_height)
@ -120,7 +120,7 @@ void Bowling::update(float dt)
if(vlen<0.8*m_speed*m_speed)
{ // bowling lost energy (less than 80%), i.e. it's too slow - speed it up:
if(vlen==0.0f) {
v = btVector3(.5f, .5f, 0.0f); // avoid 0 div.
v = btVector3(.5f, .0, 0.5f); // avoid 0 div.
}
m_body->setLinearVelocity(v*m_speed/sqrt(vlen));
} // vlen < 0.8*m_speed*m_speed

View File

@ -42,32 +42,31 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
// collide with the track. By setting the mass to 1, collisions happen.
// (if bullet is compiled with _DEBUG, a warning will be printed the first
// time a homing-track collision happens).
float y_offset=kart->getKartLength()/2.0f + m_extend.getY()/2.0f;
float forward_offset=kart->getKartLength()/2.0f + m_extend.getZ()/2.0f;
float up_velocity = m_speed/7.0f;
// give a speed proportional to kart speed
m_speed = kart->getSpeed() * m_speed / 23.0f;
if (kart->getSpeed() < 0)
m_speed /= 3.6f; //when going backwards, decrease speed of cake by less
// give a speed proportional to kart speed. m_speed is defined in flyable
m_speed *= kart->getSpeed() / 23.0f;
//when going backwards, decrease speed of cake by less
if (kart->getSpeed() < 0) m_speed /= 3.6f;
m_speed += 16.0f;
if (m_speed < 1.0f)
m_speed = 1.0f;
if (m_speed < 1.0f) m_speed = 1.0f;
btTransform trans = kart->getTrans();
btMatrix3x3 thisKartDirMatrix = kart->getKartHeading().getBasis();
btVector3 thisKartDirVector(thisKartDirMatrix[0][1],
thisKartDirMatrix[1][1],
thisKartDirMatrix[2][1]);
float heading=atan2f(-thisKartDirVector.getX(), thisKartDirVector.getY());
float heading=kart->getHeading();
float pitch = kart->getTerrainPitch(heading);
// find closest kart in front of the current one
const Kart *closest_kart=0; btVector3 direction; float kartDistSquared;
getClosestKart(&closest_kart, &kartDistSquared, &direction, kart /* search in front of this kart */);
// Find closest kart in front of the current one
const Kart *closest_kart=0;
Vec3 direction;
float kartDistSquared;
getClosestKart(&closest_kart, &kartDistSquared, &direction,
kart /* search in front of this kart */);
// aim at this kart if 1) it's not too far, 2) if the aimed kart's speed
// allows the projectile to catch up with it
@ -75,21 +74,18 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
// this code finds the correct angle and upwards velocity to hit an opponents'
// vehicle if they were to continue travelling in the same direction and same speed
// (barring any obstacles in the way of course)
if(closest_kart != NULL && kartDistSquared < m_st_max_distance_squared && m_speed>closest_kart->getSpeed())
if(closest_kart != NULL && kartDistSquared < m_st_max_distance_squared &&
m_speed>closest_kart->getSpeed())
{
m_target = (Kart*)closest_kart;
float fire_angle = 0.0f;
float time_estimated = 0.0f;
getLinearKartItemIntersection (kart->getTrans().getOrigin(), closest_kart,
m_speed, m_gravity, y_offset,
&fire_angle, &up_velocity, &time_estimated);
getLinearKartItemIntersection (kart->getXYZ(), closest_kart,
m_speed, m_gravity, forward_offset,
&fire_angle, &up_velocity);
// apply transformation to the bullet object (without pitch)
btMatrix3x3 m;
m.setEulerZYX(0.0f, 0.0f, fire_angle /*+thisKartAngle*/);
trans.setBasis(m);
trans.setRotation(btQuaternion(btVector3(0,1,0), fire_angle));
}
else
{
@ -99,14 +95,14 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
trans = kart->getKartHeading(pitch);
}
m_initial_velocity = btVector3(0.0f, m_speed, up_velocity);
m_initial_velocity = Vec3(0.0f, up_velocity, m_speed);
createPhysics(y_offset, m_initial_velocity,
createPhysics(forward_offset, m_initial_velocity,
new btCylinderShape(0.5f*m_extend), -m_gravity,
true /* rotation */, false /* backwards */, &trans);
//do not adjust height according to terrain
setAdjustZVelocity(false);
setAdjustUpVelocity(false);
m_body->setActivationState(DISABLE_DEACTIVATION);
@ -122,12 +118,11 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
void Cake::init(const XMLNode &node, scene::IMesh *cake_model)
{
Flyable::init(node, cake_model, POWERUP_CAKE);
m_st_max_distance = 80.0f;
m_st_max_distance = 80.0f;
m_st_max_distance_squared = 80.0f * 80.0f;
m_gravity = 9.8f;
m_gravity = 9.8f;
if (m_gravity < 0)
m_gravity *= -1;
if (m_gravity < 0) m_gravity *= -1.0f;
node.get("max-distance", &m_st_max_distance );
m_st_max_distance_squared = m_st_max_distance*m_st_max_distance;
@ -150,7 +145,7 @@ void Cake::update(float dt)
float time_estimated = 0.0f;
float up_velocity = 0.0f;
btVector3 origin = my_trans.getOrigin() - m_target->getNormal() * 0.5 * m_target->getKartHeight();
Vec3 origin = my_trans.getOrigin() - m_target->getNormal() * 0.5 * m_target->getKartHeight();
getLinearKartItemIntersection (origin, m_target,
m_speed, m_gravity, 0,

View File

@ -41,28 +41,25 @@ scene::IMesh* Flyable::m_st_model[POWERUP_MAX];
float Flyable::m_st_min_height[POWERUP_MAX];
float Flyable::m_st_max_height[POWERUP_MAX];
float Flyable::m_st_force_updown[POWERUP_MAX];
btVector3 Flyable::m_st_extend[POWERUP_MAX];
Vec3 Flyable::m_st_extend[POWERUP_MAX];
// ----------------------------------------------------------------------------
Flyable::Flyable(Kart *kart, PowerupType type, float mass) : Moveable()
{
// get the appropriate data from the static fields
m_speed = m_st_speed[type];
m_extend = m_st_extend[type];
m_max_height = m_st_max_height[type];
m_min_height = m_st_min_height[type];
m_average_height = (m_min_height+m_max_height)/2.0f;
m_force_updown = m_st_force_updown[type];
m_owner = kart;
m_type = type;
m_has_hit_something = false;
m_exploded = false;
m_shape = NULL;
m_mass = mass;
m_adjust_z_velocity = true;
m_time_since_thrown = 0;
m_speed = m_st_speed[type];
m_extend = m_st_extend[type];
m_max_height = m_st_max_height[type];
m_min_height = m_st_min_height[type];
m_average_height = (m_min_height+m_max_height)/2.0f;
m_force_updown = m_st_force_updown[type];
m_owner = kart;
m_has_hit_something = false;
m_exploded = false;
m_shape = NULL;
m_mass = mass;
m_adjust_up_velocity = true;
m_time_since_thrown = 0;
m_owner_has_temporary_immunity = true;
m_max_lifespan = -1;
@ -71,19 +68,32 @@ Flyable::Flyable(Kart *kart, PowerupType type, float mass) : Moveable()
} // Flyable
// ----------------------------------------------------------------------------
void Flyable::createPhysics(float y_offset, const btVector3 &velocity,
/** Creates a bullet physics body for the flyable item.
* \param forw_offset How far ahead of the kart the flyable should be
* positioned. Necessary to avoid exploding a rocket inside of the
* firing kart.
* \param velocity Initial velocity of the flyable.
* \param shape Collision shape of the flyable.
* \param gravity Gravity to use for this flyable.
* \param rotates True if the item should rotate, otherwise the angular factor
* is set to 0 preventing rotations from happening.
* \param turn_around True if the item is fired backwards.
* \param custom_direction If defined the initial heading for this item,
* otherwise the kart's heading will be used.
*/
void Flyable::createPhysics(float forw_offset, const Vec3 &velocity,
btCollisionShape *shape, const float gravity,
const bool rotates, const bool turn_around,
const btTransform* customDirection)
const btTransform* custom_direction)
{
// Get Kart heading direction
btTransform trans = ( customDirection == NULL ? m_owner->getKartHeading() : *customDirection );
btTransform trans = ( custom_direction == NULL ? m_owner->getKartHeading()
: *custom_direction );
// Apply offset
btTransform offset_transform;
offset_transform.setIdentity();
btVector3 offset=btVector3(0,y_offset,m_average_height);
offset_transform.setOrigin(offset);
offset_transform.setOrigin(Vec3(0,m_average_height,forw_offset));
// turn around
if(turn_around)
@ -91,7 +101,7 @@ void Flyable::createPhysics(float y_offset, const btVector3 &velocity,
btTransform turn_around_trans;
//turn_around_trans.setOrigin(trans.getOrigin());
turn_around_trans.setIdentity();
turn_around_trans.setRotation(btQuaternion(btVector3(0, 0, 1), M_PI));
turn_around_trans.setRotation(btQuaternion(btVector3(0, 1, 0), M_PI));
trans *= turn_around_trans;
}
@ -102,7 +112,7 @@ void Flyable::createPhysics(float y_offset, const btVector3 &velocity,
m_user_pointer.set(this);
World::getWorld()->getPhysics()->addBody(getBody());
m_body->setGravity(btVector3(0.0f, 0.0f, gravity));
m_body->setGravity(btVector3(0.0f, gravity, 0));
// Rotate velocity to point in the right direction
btVector3 v=trans.getBasis()*velocity;
@ -143,10 +153,18 @@ Flyable::~Flyable()
} // ~Flyable
//-----------------------------------------------------------------------------
/** Returns information on what is the closest kart and at what distance it is.
* All 3 parameters first are of type 'out'. 'inFrontOf' can be set if you
* wish to know the closest kart in front of some karts (will ignore those
* behind). Useful e.g. for throwing projectiles in front only.
*/
void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
btVector3 *minDelta, const Kart* inFrontOf, const bool backwards) const
Vec3 *minDelta, const Kart* inFrontOf,
const bool backwards) const
{
btTransform tProjectile = (inFrontOf != NULL ? inFrontOf->getTrans() : getTrans());
btTransform tProjectile = (inFrontOf != NULL ? inFrontOf->getTrans()
: getTrans());
*minDistSquared = -1.0f;
*minKart = NULL;
@ -158,24 +176,23 @@ void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
if(kart->isEliminated() || kart == m_owner || kart->isRescue() ) continue;
btTransform t=kart->getTrans();
btVector3 delta = t.getOrigin()-tProjectile.getOrigin();
Vec3 delta = t.getOrigin()-tProjectile.getOrigin();
float distance2 = delta.length2();
if(inFrontOf != NULL)
{
// Ignore karts behind the current one
btVector3 to_target = kart->getXYZ() - inFrontOf->getXYZ();
Vec3 to_target = kart->getXYZ() - inFrontOf->getXYZ();
const float distance = to_target.length();
if(distance > 50) continue; // kart too far, don't aim at it
btTransform trans = inFrontOf->getTrans();
// get heading=trans.getBasis*(0,1,0) ... so save the multiplication:
btVector3 direction(trans.getBasis()[0][1],
trans.getBasis()[1][1],
trans.getBasis()[2][1]);
// get heading=trans.getBasis*(0,0,1) ... so save the multiplication:
Vec3 direction(trans.getBasis().getColumn(2));
// Originally it used angle = to_target.angle( backwards ? -direction : direction );
// but since sometimes due to rounding errors we get an acos(x) with x>1, causing
// an assertion failure. So we remove the whole acos() test here:
// but sometimes due to rounding errors we get an acos(x) with x>1, causing
// an assertion failure. So we remove the whole acos() test here and copy the
// code from to_target.angle(...)
Vec3 v = backwards ? -direction : direction;
float s = sqrt(v.length2() * to_target.length2());
float c = to_target.dot(v)/s;
@ -195,42 +212,52 @@ void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
} // getClosestKart
//-----------------------------------------------------------------------------
void Flyable::getLinearKartItemIntersection (const btVector3 origin, const Kart *target_kart,
float item_XY_speed, float gravity, float y_offset,
float *fire_angle, float *up_velocity, float *time_estimated)
/** Returns information on the parameters needed to hit a target kart moving
* at constant velocity and direction for a given speed in the XZ-plane.
* \param origin Location of the kart shooting the item.
* \param target_kart Which kart to target.
* \param item_xz_speed Speed of the item projected in XZ plane.
* \param gravity The gravity used for this item.
* \param forw_offset How far ahead of the kart the item is shot (so that
* the item does not originate inside of the shooting kart.
* \param fire_angle Returns the angle to fire the item at.
* \param up_velocity Returns the upwards velocity to use for the item.
*/
void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
const Kart *target_kart,
float item_XZ_speed,
float gravity, float forw_offset,
float *fire_angle,
float *up_velocity)
{
Vec3 relative_target_kart_loc = target_kart->getTrans().getOrigin() - origin;
Vec3 relative_target_kart_loc = target_kart->getXYZ() - origin;
btTransform trans = target_kart->getTrans();
Vec3 target_direction(trans.getBasis()[0][1],
trans.getBasis()[1][1],
trans.getBasis()[2][1]);
Vec3 target_direction(trans.getBasis().getColumn(2));
float dx = relative_target_kart_loc.getX();
float dy = relative_target_kart_loc.getY();
float dz = relative_target_kart_loc.getZ();
float gx = target_direction.getX();
float gy = target_direction.getY();
float gz = target_direction.getZ();
float target_kart_speed = target_direction.length_2d() * target_kart->getSpeed(); //Projected onto X-Y plane
//Projected onto X-Z plane
float target_kart_speed = target_direction.length_2d() * target_kart->getSpeed();
float target_kart_heading = atan2f(-gx, gy); //anti-clockwise
float target_kart_heading = target_kart->getHeading();
float dist = -(target_kart_speed / item_XY_speed) * (dx * cosf(target_kart_heading) + dy * sinf(target_kart_heading));
float dist = -(target_kart_speed / item_XZ_speed) * (dx * cosf(target_kart_heading) +
dz * sinf(target_kart_heading));
float fire_th = (dx*dist - dy * sqrtf(dx*dx + dy*dy - dist*dist)) / (dx*dx + dy*dy);
fire_th = (((dist - dx*fire_th) / dy < 0) ? -acosf(fire_th): acosf(fire_th));
float fire_th = (dx*dist - dz * sqrtf(dx*dx + dz*dz - dist*dist)) / (dx*dx + dz*dz);
fire_th = (((dist - dx*fire_th) / dz > 0) ? -acosf(fire_th): acosf(fire_th));
float time = 0.0f;
float a = item_XY_speed * sinf (fire_th) + target_kart_speed * sinf (target_kart_heading);
float b = item_XY_speed * cosf (fire_th) + target_kart_speed * cosf (target_kart_heading);
float a = item_XZ_speed * sinf (fire_th) + target_kart_speed * sinf (target_kart_heading);
float b = item_XZ_speed * cosf (fire_th) + target_kart_speed * cosf (target_kart_heading);
if (fabsf(a) > fabsf(b))
time = fabsf (dx / a);
else if (b != 0.0f)
time = fabsf(dy / b);
if (fabsf(a) > fabsf(b)) time = fabsf (dx / a);
else if (b != 0.0f) time = fabsf(dz / b);
if (fire_th > M_PI)
fire_th -= M_PI;
@ -238,12 +265,11 @@ void Flyable::getLinearKartItemIntersection (const btVector3 origin, const Kart
fire_th += M_PI;
//createPhysics offset
time -= y_offset / sqrt(a*a+b*b);
time -= forw_offset / sqrt(a*a+b*b);
*fire_angle = fire_th;
*up_velocity = (0.5f * time * gravity) + (dz / time) + (gz * target_kart->getSpeed());
*time_estimated = time;
}
*up_velocity = (0.5f * time * gravity) + (dy / time) + (gy * target_kart->getSpeed());
} // getLinearKartItemIntersection
//-----------------------------------------------------------------------------
void Flyable::update(float dt)
@ -260,15 +286,15 @@ void Flyable::update(float dt)
const Vec3 *min, *max;
World::getWorld()->getTrack()->getAABB(&min, &max);
Vec3 xyz = getXYZ();
if(xyz[0]<(*min)[0] || xyz[1]<(*min)[1] || xyz[2]<(*min)[2] ||
xyz[0]>(*max)[0] || xyz[1]>(*max)[1] )
if(xyz[0]<(*min)[0] || xyz[2]<(*min)[2] || xyz[1]<(*min)[1] ||
xyz[0]>(*max)[0] || xyz[2]>(*max)[2] )
{
hit(NULL); // flyable out of track boundary
return;
}
if(m_adjust_z_velocity)
if(m_adjust_up_velocity)
{
float hat = pos.getZ()-getHoT();
float hat = pos.getY()-getHoT();
// Use the Height Above Terrain to set the Z velocity.
// HAT is clamped by min/max height. This might be somewhat
@ -276,14 +302,14 @@ void Flyable::update(float dt)
float delta = m_average_height - std::max(std::min(hat, m_max_height), m_min_height);
Vec3 v = getVelocity();
float heading = atan2f(-v.getX(), v.getY());
float pitch = getTerrainPitch (heading);
float vel_z = m_force_updown*(delta);
float heading = atan2f(v.getX(), v.getZ());
float pitch = getTerrainPitch(heading);
float vel_up = m_force_updown*(delta);
if (hat < m_max_height) // take into account pitch of surface
vel_z += v.length_2d()*tanf(pitch);
v.setZ(vel_z);
vel_up += v.length_2d()*tanf(pitch);
v.setY(vel_up);
setVelocity(v);
} // if m_adjust_z_velocity
} // if m_adjust_up_velocity
Moveable::update(dt);
} // update

View File

@ -45,10 +45,10 @@ private:
* It can happen that more than one collision between a rocket and
* a track or kart is reported by the physics. */
bool m_exploded;
/** If this flag is set, the Z velocity of the kart will not be
/** If this flag is set, the up velocity of the kart will not be
* adjusted in case that the objects is too high or too low above the
* terrain. Otherwise gravity will not work correctly on this object. */
bool m_adjust_z_velocity;
bool m_adjust_up_velocity;
protected:
Kart* m_owner; // the kart which released this flyable
@ -60,7 +60,7 @@ protected:
float m_force_updown;
float m_speed;
float m_mass;
btVector3 m_extend;
Vec3 m_extend;
// The flyable class stores the values for each flyable type, e.g.
// speed, min_height, max_height. These variables must be static,
// so we need arrays of these variables to have different values
@ -70,7 +70,7 @@ protected:
static float m_st_min_height[POWERUP_MAX]; // min height above track
static float m_st_max_height[POWERUP_MAX]; // max height above track
static float m_st_force_updown[POWERUP_MAX]; // force pushing up/down
static btVector3 m_st_extend[POWERUP_MAX]; // size of the model
static Vec3 m_st_extend[POWERUP_MAX]; // size of the model
/** time since thrown. used so a kart can't hit himself when trying something,
and also to put some time limit to some collectibles */
@ -83,28 +83,20 @@ protected:
for a short time */
bool m_owner_has_temporary_immunity;
/** Returns information on what is the closest kart and at what
distance it is. All 3 parameters first are of type 'out'.
'inFrontOf' can be set if you wish to know the closest
kart in front of some karts (will ignore those behind).
Useful e.g. for throwing projectiles in front only.
*/
void getClosestKart(const Kart **minKart, float *minDistSquared,
btVector3 *minDelta, const Kart* inFrontOf=NULL,
Vec3 *minDelta, const Kart* inFrontOf=NULL,
const bool backwards=false) const;
/** Returns information on the parameters needed to hit a target kart
moving at constant velocity and direction for a given speed in the
XY-plane.
*/
void getLinearKartItemIntersection(const btVector3 origin, const Kart *target_kart,
float item_XY_velocity, float gravity, float y_offset,
float *fire_angle, float *up_velocity, float *time);
void getLinearKartItemIntersection(const Vec3 &origin,
const Kart *target_kart,
float item_XY_velocity, float gravity,
float forw_offset,
float *fire_angle, float *up_velocity);
/** init bullet for moving objects like projectiles */
void createPhysics(float y_offset,
const btVector3 &velocity,
const Vec3 &velocity,
btCollisionShape *shape, const float gravity=0.0f,
const bool rotates=false, const bool turn_around=false,
const btTransform* customDirection=NULL);
@ -115,7 +107,7 @@ public:
/** Enables/disables adjusting ov velocity depending on height above
* terrain. Missiles can 'follow the terrain' with this adjustment,
* but gravity will basically be disabled. */
void setAdjustZVelocity(bool f) { m_adjust_z_velocity = f; }
void setAdjustUpVelocity(bool f) { m_adjust_up_velocity = f; }
static void init (const XMLNode &node, scene::IMesh *model,
PowerupType type);
virtual void update (float);

View File

@ -31,13 +31,10 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
{
setType(type);
m_event_handler = NULL;
m_xyz = xyz;
m_deactive_time = 0;
m_normal = normal;
// Sets heading to 0, and sets pitch and roll depending on the normal. */
Vec3 hpr = Vec3(0, normal);
m_coord = Coord(xyz, hpr);
m_rotate_to_normal = core::quaternion(hpr.toIrrVector());
m_rotate_amount = 0;
m_item_id = item_id;
m_original_type = ITEM_NONE;
m_collected = false;
@ -148,8 +145,6 @@ void Item::update(float dt)
// Make it visible by scaling it from 0 to 1:
m_node->setVisible(true);
m_node->setScale(core::vector3df(1,1,1)*(1-m_time_till_return));
core::vector3df pos = m_coord.getXYZ().toIrrVector();
pos.Y = pos.Y+2.0f*m_time_till_return;
} // time till return < 1
} // if collected
else
@ -157,59 +152,13 @@ void Item::update(float dt)
if(!m_rotate) return;
// have it rotate
Vec3 rotation(dt*M_PI, 0, 0);
m_coord.setHPR(m_coord.getHPR()+rotation);
m_node->setRotation(m_coord.getHPR().toIrrHPR());
m_node->setPosition(m_coord.getXYZ().toIrrVector());
Vec3 rotation(0, dt*M_PI, 0);
core::vector3df r = m_node->getRotation();
r.Y += dt*180.0f;
if(r.Y>360.0f) r.Y -= 360.0f;
m_node->setRotation(r);
return;
m_rotate_amount += dt*M_PI;
if(m_rotate_amount>2*M_PI) m_rotate_amount -= 2*M_PI;
core::quaternion qx;
qx.fromAngleAxis(m_rotate_amount, m_normal.toIrrVector());
core::quaternion qall = m_rotate_to_normal*qx;
core::vector3df qeuler;
qx.toEuler(qeuler);
qeuler *= 180/3.1415926f;
m_node->setRotation(qeuler);
return;
const core::matrix4 &m=m_node->getAbsoluteTransformation();
core::quaternion current_rotation(m);
float anglec;
core::vector3df axisc;
current_rotation.toAngleAxis(anglec, axisc);
printf("curre %f axis %f %f %f\n", anglec,axisc.X, axisc.Y, axisc.Z);
core::quaternion q2;
q2.fromAngleAxis(dt*M_PI, m_normal.toIrrVector());
float angle2;
core::vector3df axis2;
q2.toAngleAxis(angle2, axis2);
printf("new %f axis %f %f %f\n", angle2,axis2.X, axis2.Y, axis2.Z);
core::quaternion all=current_rotation*q2;
float angle;
core::vector3df axis;
all.toAngleAxis(angle, axis);
printf("angle %f axis %f %f %f\n", angle,axis.X, axis.Y, axis.Z);
core::vector3df euler;
all.toEuler(euler);
euler *=180/3.1415926f;
m_node->setRotation(euler);
return;
#ifdef xx
btQuaternion q(Vec3(0,0,1), t*0.1f);
btQuaternion q_orig(m_normal, 0);
btQuaternion result=q+q_orig;
btMatrix3x3 m(result);
float y, p, r;
m.getEuler(y, p, r);
m_node->setRotation(Vec3(y, p, r).toIrrHPR());
#endif
}
} // not m_collected
} // update
//-----------------------------------------------------------------------------

View File

@ -60,18 +60,15 @@ private:
/** Time till a collected item reappears. */
float m_time_till_return;
/** Original coordinates, used mainly when collected items reappear. */
Coord m_coord;
core::quaternion m_rotate_to_normal;
float m_rotate_amount;
/** Scene node of this item. */
scene::IMeshSceneNode *m_node;
/** Stores the original mesh in order to reset it. */
scene::IMesh *m_original_mesh;
Vec3 m_normal;
/** The original position - saves calls to m_node->getPosition()
* and then converting this value to a Vec3. */
Vec3 m_xyz;
/** Index in item_manager field. */
unsigned int m_item_id;
@ -79,11 +76,12 @@ private:
/** Set to false if item should not rotate. */
bool m_rotate;
/** optionally, set this if this item was laid by a particular kart. in this case,
the 'm_deactive_time' will also be set - see below. */
/** Optionally set this if this item was laid by a particular kart. in
* this case the 'm_deactive_time' will also be set - see below. */
const Kart *m_event_handler;
/** optionally, if item was placed by a kart, a timer can be used to temporarly
deactivate collision so a kart is not hit by its own item */
/** Optionally if item was placed by a kart, a timer can be used to
* temporarly deactivate collision so a kart is not hit by its own item */
float m_deactive_time;
void setType(ItemType type);
@ -102,7 +100,7 @@ public:
bool hitKart (Kart* kart ) const
{
return (m_event_handler!=kart || m_deactive_time <=0) &&
(kart->getXYZ()-m_coord.getXYZ()).length2()<0.8f;
(kart->getXYZ()-m_xyz).length2()<0.8f;
} // hitKart
// ------------------------------------------------------------------------

View File

@ -46,48 +46,46 @@ Plunger::Plunger(Kart *kart) : Flyable(kart, POWERUP_PLUNGER)
m_reverse_mode = kart->getControls().m_look_back;
// find closest kart in front of the current one
const Kart *closest_kart=0; btVector3 direction; float kartDistSquared;
getClosestKart(&closest_kart, &kartDistSquared, &direction, kart /* search in front of this kart */, m_reverse_mode);
const Kart *closest_kart=0;
Vec3 direction;
float kartDistSquared;
getClosestKart(&closest_kart, &kartDistSquared, &direction,
kart /* search in front of this kart */, m_reverse_mode);
btTransform trans = kart->getTrans();
btMatrix3x3 thisKartDirMatrix = kart->getKartHeading().getBasis();
btVector3 thisKartDirVector(thisKartDirMatrix[0][1],
thisKartDirMatrix[1][1],
thisKartDirMatrix[2][1]);
btVector3 thisKartDirVector(thisKartDirMatrix.getColumn(2));
float heading=atan2f(-thisKartDirVector.getX(), thisKartDirVector.getY());
float heading=kart->getHeading();
float pitch = kart->getTerrainPitch(heading);
// aim at this kart if it's not too far
if(closest_kart != NULL && kartDistSquared < 30*30)
{
float fire_angle = 0.0f;
float time_estimated = 0.0f;
getLinearKartItemIntersection (kart->getTrans().getOrigin(), closest_kart,
getLinearKartItemIntersection (kart->getXYZ(), closest_kart,
plunger_speed, gravity, y_offset,
&fire_angle, &up_velocity, &time_estimated);
&fire_angle, &up_velocity);
// apply transformation to the bullet object (without pitch)
btMatrix3x3 m;
m.setEulerZYX(0.0f, 0.0f, fire_angle);
trans.setBasis(m);
trans.setRotation(btQuaternion(btVector3(0, 1, 0), fire_angle));
m_initial_velocity = btVector3(0.0f, plunger_speed, up_velocity);
m_initial_velocity = btVector3(0.0f, up_velocity, plunger_speed);
createPhysics(y_offset, m_initial_velocity,
new btCylinderShape(0.5f*m_extend), gravity, false /* rotates */, false, &trans );
new btCylinderShape(0.5f*m_extend), gravity,
/* rotates */false , /*turn around*/false, &trans );
}
else
{
trans = kart->getKartHeading();
createPhysics(y_offset, btVector3(pitch, plunger_speed, 0.0f),
createPhysics(y_offset, btVector3(pitch, 0.0f, plunger_speed),
new btCylinderShape(0.5f*m_extend), gravity, false /* rotates */, m_reverse_mode, &trans );
}
//adjust height according to terrain
setAdjustZVelocity(true);
setAdjustUpVelocity(true);
// pulling back makes no sense in battle mode, since this mode is not a race.
// so in battle mode, always hide view
@ -166,11 +164,10 @@ void Plunger::hit(Kart *kart, PhysicalObject *obj)
}
m_keep_alive = 0;
// Make this object invisible by placing it faaar down. Not that if this
// Make this object invisible by placing it faaar down. Note that if this
// objects is simply removed from the scene graph, it might be auto-deleted
// because the ref count reaches zero.
Vec3 hell(0, 0, -10000);
getNode()->setPosition(hell.toIrrVector());
getNode()->setVisible(false);
World::getWorld()->getPhysics()->removeBody(getBody());
}
else
@ -183,8 +180,7 @@ void Plunger::hit(Kart *kart, PhysicalObject *obj)
scene::ISceneNode *node = getNode();
if(node)
{
Vec3 hell(0, 0, -10000);
getNode()->setPosition(hell.toIrrVector());
node->setVisible(false);
}
World::getWorld()->getPhysics()->removeBody(getBody());

View File

@ -91,10 +91,10 @@ void RubberBand::updatePosition()
const float hh=.1f; // half height of the band
const Vec3 &p=m_end_position; // for shorter typing
irr::video::S3DVertex* v=(video::S3DVertex*)m_buffer->getVertices();
v[0].Pos.X = p.getX()-hh; v[0].Pos.Z=p.getY(); v[0].Pos.Y = p.getZ()-hh;
v[1].Pos.X = p.getX()+hh; v[1].Pos.Z=p.getY(); v[1].Pos.Y = p.getZ()+hh;
v[2].Pos.X = k.getX()+hh; v[2].Pos.Z=k.getY(); v[2].Pos.Y = k.getZ()+hh;
v[3].Pos.X = k.getX()-hh; v[3].Pos.Z=k.getY(); v[3].Pos.Y = k.getZ()-hh;
v[0].Pos.X = p.getX()-hh; v[0].Pos.Y=p.getY(); v[0].Pos.Z = p.getZ()-hh;
v[1].Pos.X = p.getX()+hh; v[1].Pos.Y=p.getY(); v[1].Pos.Z = p.getZ()+hh;
v[2].Pos.X = k.getX()+hh; v[2].Pos.Y=k.getY(); v[2].Pos.Z = k.getZ()+hh;
v[3].Pos.X = k.getX()-hh; v[3].Pos.Y=k.getY(); v[3].Pos.Z = k.getZ()-hh;
m_buffer->recalculateBoundingBox();
m_mesh->setBoundingBox(m_buffer->getBoundingBox());
} // updatePosition

View File

@ -299,13 +299,13 @@ void DefaultAIController::handleBraking()
//We may brake if we are about to get out of the road, but only if the
//kart is on top of the road, and if we won't slow down below a certain
//limit.
if (m_crashes.m_road && m_kart->getVelocityLC().getY() > MIN_SPEED &&
if (m_crashes.m_road && m_kart->getVelocityLC().getZ() > MIN_SPEED &&
m_world->isOnRoad(m_kart->getWorldKartId()) )
{
float kart_ang_diff =
m_quad_graph->getAngleToNext(m_track_node,
m_successor_index[m_track_node])
- m_kart->getHPR().getHeading();
- m_kart->getHeading();
kart_ang_diff = normalizeAngle(kart_ang_diff);
kart_ang_diff = fabsf(kart_ang_diff);
@ -341,7 +341,7 @@ void DefaultAIController::handleBraking()
//Brake if the kart's speed is bigger than the speed we need
//to go through the curve at the widest angle, or if the kart
//is not going straight in relation to the road.
if(m_kart->getVelocityLC().getY() > m_curve_target_speed ||
if(m_kart->getVelocityLC().getZ() > m_curve_target_speed ||
kart_ang_diff > MIN_TRACK_ANGLE )
{
#ifdef AI_DEBUG
@ -778,7 +778,7 @@ float DefaultAIController::steerToAngle(const size_t SECTOR, const float ANGLE)
m_successor_index[SECTOR]);
//Desired angle minus current angle equals how many angles to turn
float steer_angle = angle - m_kart->getHPR().getHeading();
float steer_angle = angle - m_kart->getHeading();
if(m_kart->hasViewBlockedByPlunger())
steer_angle += ANGLE/5;
@ -802,15 +802,15 @@ float DefaultAIController::steerToPoint(const Vec3 &point, float dt)
// No sense steering if we are not driving.
if(m_kart->getSpeed()==0) return 0.0f;
const float dx = point.getX() - m_kart->getXYZ().getX();
const float dy = point.getY() - m_kart->getXYZ().getY();
const float dz = point.getZ() - m_kart->getXYZ().getZ();
/** Angle from the kart position to the point in world coordinates. */
float theta = -atan2(dx, dy);
float theta = atan2(dx, dz);
// Angle is the point is relative to the heading - but take the current
// angular velocity into account, too. The value is multiplied by two
// to avoid 'oversteering' - experimentally found.
float angle_2_point = theta - m_kart->getHPR().getHeading()
- dt*m_kart->getBody()->getAngularVelocity().getZ()*2.0f;
float angle_2_point = theta - m_kart->getHeading()
- dt*m_kart->getBody()->getAngularVelocity().getY()*2.0f;
angle_2_point = normalizeAngle(angle_2_point);
if(fabsf(angle_2_point)<0.1) return 0.0f;
@ -830,7 +830,7 @@ float DefaultAIController::steerToPoint(const Vec3 &point, float dt)
float sin_steer_angle = m_kart->getKartProperties()->getWheelBase()/radius;
#ifdef DEBUG_OUTPUT
printf("theta %f a2p %f angularv %f radius %f ssa %f\n",
theta, angle_2_point, m_body->getAngularVelocity().getZ(),
theta, angle_2_point, m_body->getAngularVelocity().getY(),
radius, sin_steer_angle);
#endif
// Add 0.1 since rouding errors will otherwise result in the kart
@ -857,7 +857,7 @@ void DefaultAIController::checkCrashes( const int STEPS, const Vec3& pos )
//Protection against having vel_normal with nan values
const Vec3 &VEL = m_kart->getVelocity();
Vec3 vel_normal(VEL.getX(), VEL.getY(), 0.0);
Vec3 vel_normal(VEL.getX(), VEL.getZ(), 0.0);
float speed=vel_normal.length();
// If the velocity is zero, no sense in checking for crashes in time
if(speed==0) return;
@ -882,7 +882,7 @@ void DefaultAIController::checkCrashes( const int STEPS, const Vec3& pos )
if(kart==m_kart||kart->isEliminated()) continue; // ignore eliminated karts
const Kart *other_kart = m_world->getKart(j);
// Ignore karts ahead that are faster than this kart.
if(m_kart->getVelocityLC().getY() < other_kart->getVelocityLC().getY())
if(m_kart->getVelocityLC().getZ() < other_kart->getVelocityLC().getZ())
continue;
Vec3 other_kart_xyz = other_kart->getXYZ() + other_kart->getVelocity()*(i*dt);
float kart_distance = (step_coord - other_kart_xyz).length_2d();
@ -1012,7 +1012,7 @@ inline float DefaultAIController::normalizeAngle(float angle)
*/
int DefaultAIController::calcSteps()
{
int steps = int( m_kart->getVelocityLC().getY() / m_kart_length );
int steps = int( m_kart->getVelocityLC().getZ() / m_kart_length );
if( steps < m_min_steps ) steps = m_min_steps;
//Increase the steps depending on the width, if we steering hard,
@ -1086,7 +1086,7 @@ void DefaultAIController::findCurve()
{
float total_dist = 0.0f;
int i;
for(i = m_track_node; total_dist < m_kart->getVelocityLC().getY();
for(i = m_track_node; total_dist < m_kart->getVelocityLC().getZ();
i = m_next_node_index[i])
{
total_dist += m_quad_graph->getDistanceToNext(i, m_successor_index[i]);

View File

@ -301,7 +301,7 @@ float EndController::steerToAngle(const size_t SECTOR, const float ANGLE)
m_successor_index[SECTOR]);
//Desired angle minus current angle equals how many angles to turn
float steer_angle = angle - m_kart->getHPR().getHeading();
float steer_angle = angle - m_kart->getHeading();
if(m_kart->hasViewBlockedByPlunger())
steer_angle += ANGLE/5;
@ -325,15 +325,15 @@ float EndController::steerToPoint(const Vec3 &point, float dt)
// No sense steering if we are not driving.
if(m_kart->getSpeed()==0) return 0.0f;
const float dx = point.getX() - m_kart->getXYZ().getX();
const float dy = point.getY() - m_kart->getXYZ().getY();
const float dz = point.getZ() - m_kart->getXYZ().getZ();
/** Angle from the kart position to the point in world coordinates. */
float theta = -atan2(dx, dy);
float theta = atan2(dx, dz);
// Angle is the point is relative to the heading - but take the current
// angular velocity into account, too. The value is multiplied by two
// to avoid 'oversteering' - experimentally found.
float angle_2_point = theta - m_kart->getHPR().getHeading()
- dt*m_kart->getBody()->getAngularVelocity().getZ()*2.0f;
float angle_2_point = theta - m_kart->getHeading()
- dt*m_kart->getBody()->getAngularVelocity().getY()*2.0f;
angle_2_point = normalizeAngle(angle_2_point);
if(fabsf(angle_2_point)<0.1) return 0.0f;
@ -353,7 +353,7 @@ float EndController::steerToPoint(const Vec3 &point, float dt)
float sin_steer_angle = m_kart->getKartProperties()->getWheelBase()/radius;
#ifdef DEBUG_OUTPUT
printf("theta %f a2p %f angularv %f radius %f ssa %f\n",
theta, angle_2_point, m_body->getAngularVelocity().getZ(),
theta, angle_2_point, m_body->getAngularVelocity().getY(),
radius, sin_steer_angle);
#endif
// Add 0.1 since rouding errors will otherwise result in the kart
@ -463,7 +463,7 @@ inline float EndController::normalizeAngle(float angle)
*/
int EndController::calcSteps()
{
int steps = int( m_kart->getVelocityLC().getY() / m_kart_length );
int steps = int( m_kart->getVelocityLC().getZ() / m_kart_length );
if( steps < m_min_steps ) steps = m_min_steps;
//Increase the steps depending on the width, if we steering hard,
@ -537,7 +537,7 @@ void EndController::findCurve()
{
float total_dist = 0.0f;
int i;
for(i = m_track_node; total_dist < m_kart->getVelocityLC().getY();
for(i = m_track_node; total_dist < m_kart->getVelocityLC().getZ();
i = m_next_node_index[i])
{
total_dist += m_quad_graph->getDistanceToNext(i, m_successor_index[i]);

View File

@ -295,13 +295,13 @@ void NewAIController::handleBraking()
//We may brake if we are about to get out of the road, but only if the
//kart is on top of the road, and if we won't slow down below a certain
//limit.
if (m_crashes.m_road && m_kart->getVelocityLC().getY() > MIN_SPEED &&
if (m_crashes.m_road && m_kart->getVelocityLC().getZ() > MIN_SPEED &&
m_world->isOnRoad(m_kart->getWorldKartId()) )
{
float kart_ang_diff =
m_quad_graph->getAngleToNext(m_track_node,
m_successor_index[m_track_node])
- m_kart->getHPR().getHeading();
- m_kart->getHeading();
kart_ang_diff = normalizeAngle(kart_ang_diff);
kart_ang_diff = fabsf(kart_ang_diff);
@ -337,7 +337,7 @@ void NewAIController::handleBraking()
//Brake if the kart's speed is bigger than the speed we need
//to go through the curve at the widest angle, or if the kart
//is not going straight in relation to the road.
if(m_kart->getVelocityLC().getY() > m_curve_target_speed ||
if(m_kart->getVelocityLC().getZ() > m_curve_target_speed ||
kart_ang_diff > MIN_TRACK_ANGLE )
{
#ifdef AI_DEBUG
@ -765,7 +765,7 @@ float NewAIController::steerToAngle(const size_t SECTOR, const float ANGLE)
m_successor_index[SECTOR]);
//Desired angle minus current angle equals how many angles to turn
float steer_angle = angle - m_kart->getHPR().getHeading();
float steer_angle = angle - m_kart->getHeading();
if(m_kart->hasViewBlockedByPlunger())
steer_angle += ANGLE/5;
@ -789,15 +789,15 @@ float NewAIController::steerToPoint(const Vec3 &point, float dt)
// No sense steering if we are not driving.
if(m_kart->getSpeed()==0) return 0.0f;
const float dx = point.getX() - m_kart->getXYZ().getX();
const float dy = point.getY() - m_kart->getXYZ().getY();
const float dz = point.getZ() - m_kart->getXYZ().getZ();
/** Angle from the kart position to the point in world coordinates. */
float theta = -atan2(dx, dy);
float theta = atan2(dx, dz);
// Angle is the point is relative to the heading - but take the current
// angular velocity into account, too. The value is multiplied by two
// to avoid 'oversteering' - experimentally found.
float angle_2_point = theta - m_kart->getHPR().getHeading()
- dt*m_kart->getBody()->getAngularVelocity().getZ()*2.0f;
float angle_2_point = theta - m_kart->getHeading()
- dt*m_kart->getBody()->getAngularVelocity().getY()*2.0f;
angle_2_point = normalizeAngle(angle_2_point);
if(fabsf(angle_2_point)<0.1) return 0.0f;
@ -817,7 +817,7 @@ float NewAIController::steerToPoint(const Vec3 &point, float dt)
float sin_steer_angle = m_kart->getKartProperties()->getWheelBase()/radius;
#ifdef DEBUG_OUTPUT
printf("theta %f a2p %f angularv %f radius %f ssa %f\n",
theta, angle_2_point, m_body->getAngularVelocity().getZ(),
theta, angle_2_point, m_body->getAngularVelocity().getY(),
radius, sin_steer_angle);
#endif
// Add 0.1 since rouding errors will otherwise result in the kart
@ -904,10 +904,10 @@ float NewAIController::findNonCrashingAngle()
float very_right = -atan2(right.getX()-xyz.getX(),
right.getY()-xyz.getY())
- m_kart->getHPR().getHeading();
- m_kart->getHeading();
float very_left = -atan2(left.getX()-xyz.getX(),
left.getY()-xyz.getY())
- m_kart->getHPR().getHeading();
- m_kart->getHeading();
very_left = normalizeAngle(very_left);
very_right = normalizeAngle(very_right);
float dist = 0;
@ -920,10 +920,10 @@ float NewAIController::findNonCrashingAngle()
float angle_right = -atan2(right.getX()-xyz.getX(),
right.getY()-xyz.getY())
- m_kart->getHPR().getHeading();
- m_kart->getHeading();
float angle_left = -atan2(left.getX()-xyz.getX(),
left.getY()-xyz.getY())
- m_kart->getHPR().getHeading();
- m_kart->getHeading();
angle_left = normalizeAngle(angle_left);
angle_right = normalizeAngle(angle_right);

View File

@ -118,17 +118,17 @@ void PlayerController::action(PlayerAction action, int value)
switch (action)
{
case PA_LEFT:
m_steer_val_l = -value;
m_steer_val_l = value;
if (value)
m_steer_val = -value;
m_steer_val = value;
else
m_steer_val = m_steer_val_r;
break;
case PA_RIGHT:
m_steer_val_r = value;
m_steer_val_r = -value;
if (value)
m_steer_val = value;
m_steer_val = -value;
else
m_steer_val = m_steer_val_l;

View File

@ -80,7 +80,6 @@ Kart::Kart (const std::string& ident, int position,
m_nitro = NULL;
m_slip_stream = NULL;
m_skidmarks = NULL;
m_animated_node = NULL;
m_camera = NULL;
m_controller = NULL;
m_saved_controller = NULL;
@ -133,12 +132,12 @@ Kart::Kart (const std::string& ident, int position,
}
loadData();
float l = m_kart_properties->getSlipstreamLength();
float length = m_kart_properties->getSlipstreamLength();
Vec3 p0(-getKartWidth()*0.5f, -getKartLength()*0.5f, 0);
Vec3 p1(-getKartWidth()*0.5f, -getKartLength()*0.5f-l, 0);
Vec3 p2( getKartWidth()*0.5f, -getKartLength()*0.5f-l, 0);
Vec3 p3( getKartWidth()*0.5f, -getKartLength()*0.5f, 0);
Vec3 p0(-getKartWidth()*0.5f, 0, -getKartLength()*0.5f );
Vec3 p1(-getKartWidth()*0.5f, 0, -getKartLength()*0.5f-length);
Vec3 p2( getKartWidth()*0.5f, 0, -getKartLength()*0.5f-length);
Vec3 p3( getKartWidth()*0.5f, 0, -getKartLength()*0.5f );
m_slipstream_original_quad = new Quad(p0, p1, p2, p3);
m_slipstream_quad = new Quad(p0, p1, p2, p3);
@ -162,25 +161,21 @@ void Kart::setController(Controller *controller)
btTransform Kart::getKartHeading(const float customPitch)
{
btTransform trans = this->getTrans();
btTransform trans = getTrans();
// get heading=trans.getBasis*(0,1,0) ... so save the multiplication:
btVector3 direction(trans.getBasis()[0][1],
trans.getBasis()[1][1],
trans.getBasis()[2][1]);
float heading=atan2(-direction.getX(), direction.getY());
TerrainInfo::update(this->getXYZ());
float pitch = (customPitch == -1 ? getTerrainPitch(heading) : customPitch);
float pitch = (customPitch == -1 ? getTerrainPitch(getHeading()) : customPitch);
btMatrix3x3 m;
m.setEulerZYX(pitch, 0.0f, heading);
m.setEulerYPR(-getHeading(), pitch, 0.0f);
trans.setBasis(m);
return trans;
} // getKartHeading
// ----------------------------------------------------------------------------
/** Created the physical representation of this kart. Atm it uses the actual
* extention of the kart model to determine the size of the collision body.
*/
void Kart::createPhysics()
{
// First: Create the chassis of the kart
@ -191,8 +186,8 @@ void Kart::createPhysics()
float kart_height = km->getHeight();
btBoxShape *shape = new btBoxShape(btVector3(0.5f*kart_width,
0.5f*kart_length,
0.5f*kart_height));
0.5f*kart_height,
0.5f*kart_length));
btTransform shiftCenterOfGravity;
shiftCenterOfGravity.setIdentity();
// Shift center of gravity downwards, so that the kart
@ -229,15 +224,15 @@ void Kart::createPhysics()
// never deactivate the vehicle
m_body->setActivationState(DISABLE_DEACTIVATION);
m_vehicle->setCoordinateSystem(/*right: */ 0, /*up: */ 2, /*forward: */ 1);
m_vehicle->setCoordinateSystem(/*right: */ 0, /*up: */ 1, /*forward: */ 2);
// Add wheels
// ----------
float wheel_radius = m_kart_properties->getWheelRadius();
float suspension_rest = m_kart_properties->getSuspensionRest();
btVector3 wheel_direction(0.0f, 0.0f, -1.0f);
btVector3 wheel_axle(1.0f,0.0f,0.0f);
btVector3 wheel_direction(0.0f, -1.0f, 0.0f);
btVector3 wheel_axle(-1.0f, 0.0f, 0.0f);
for(unsigned int i=0; i<4; i++)
{
@ -255,7 +250,7 @@ void Kart::createPhysics()
// Obviously these allocs have to be properly managed/freed
btTransform t;
t.setIdentity();
m_uprightConstraint=new btUprightConstraint(*m_body, t);
m_uprightConstraint=new btUprightConstraint(this, t);
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
m_uprightConstraint->setBounce(0.0f);
m_uprightConstraint->setMaxLimitForce(m_kart_properties->getUprightMaxForce());
@ -393,10 +388,6 @@ void Kart::reset()
m_controller = m_saved_controller;
m_saved_controller = NULL;
}
// Reset is also called when the kart is created, at which time
// m_controller is not yet defined.
if(m_controller)
m_controller->reset();
m_kart_properties->getKartModel()->setEndAnimation(false);
m_view_blocked_by_plunger = 0.0;
m_attachment.clear();
@ -443,6 +434,12 @@ void Kart::reset()
}
TerrainInfo::update(getXYZ());
// Reset is also called when the kart is created, at which time
// m_controller is not yet defined, so this has to be tested here.
if(m_controller)
m_controller->reset();
} // reset
//-----------------------------------------------------------------------------
@ -681,7 +678,6 @@ void Kart::update(float dt)
else
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
m_zipper_time_left = m_zipper_time_left>0.0f ? m_zipper_time_left-dt : 0.0f;
//m_wheel_rotation gives the rotation around the X-axis, and since velocity's
@ -703,11 +699,11 @@ void Kart::update(float dt)
}
World::getWorld()->getPhysics()->removeKart(this);
btQuaternion q_roll (btVector3(0.f, 1.f, 0.f),
btQuaternion q_roll (btVector3(0.0f, 0.0f, 1.0f),
-m_rescue_roll*dt/rescue_time*M_PI/180.0f);
btQuaternion q_pitch(btVector3(1.f, 0.f, 0.f),
-m_rescue_pitch*dt/rescue_time*M_PI/180.0f);
setXYZRotation(getXYZ()+Vec3(0, 0, rescue_height*dt/rescue_time),
setXYZRotation(getXYZ()+Vec3(0, rescue_height*dt/rescue_time, 0),
getRotation()*q_roll*q_pitch);
} // if rescue mode
m_attachment.update(dt);
@ -1063,7 +1059,7 @@ bool Kart::playCustomSFX(unsigned int type)
*/
}
// -----------------------------------------------------------------------------
void Kart::updatePhysics (float dt)
void Kart::updatePhysics(float dt)
{
m_bounce_back_time-=dt;
@ -1136,30 +1132,25 @@ void Kart::updatePhysics (float dt)
if(f<0.1f) f=0.1f;
applyEngineForce(-engine_power*f);
}
else
else // -m_speed >= max speed on this terrain
{
applyEngineForce(0.0f);
}
}
} // m_speed <00
}
else
else // !m_brake
{
// lift the foot from throttle, brakes with 10% engine_power
applyEngineForce(-m_controls.m_accel*engine_power*0.1f);
#if 1
// If not giving power (forward or reverse gear), and speed is low
// we are "parking" the kart, so in battle mode we can ambush people, eg
if(abs(m_speed) < 5.0f) {
for(int i=0; i<4; i++) m_vehicle->setBrake(20.0f, i);
}
#else
if(!RaceManager::getWorld()->isStartPhase())
resetBrakes();
#endif
}
}
} // !m_brake
} // not accelerating
#ifdef ENABLE_JUMP
if(m_controls.jump && isOnGround())
{
@ -1213,9 +1204,9 @@ void Kart::updatePhysics (float dt)
// calculate direction of m_speed
const btTransform& chassisTrans = getVehicle()->getChassisWorldTransform();
btVector3 forwardW (
chassisTrans.getBasis()[0][1],
chassisTrans.getBasis()[1][1],
chassisTrans.getBasis()[2][1]);
chassisTrans.getBasis()[0][2],
chassisTrans.getBasis()[1][2],
chassisTrans.getBasis()[2][2]);
if (forwardW.dot(getVehicle()->getRigidBody()->getLinearVelocity()) < btScalar(0.))
m_speed *= -1.f;
@ -1228,7 +1219,7 @@ void Kart::updatePhysics (float dt)
m_speed = max_speed;
btVector3 velocity = m_body->getLinearVelocity();
velocity.setY( velocity.getY() * velocity_ratio );
velocity.setZ( velocity.getZ() * velocity_ratio );
velocity.setX( velocity.getX() * velocity_ratio );
getVehicle()->getRigidBody()->setLinearVelocity( velocity );
@ -1243,11 +1234,11 @@ void Kart::updatePhysics (float dt)
// to suspensionTravel / dt with dt = 1/60 (since this is the dt
// bullet is using).
const Vec3 &v = m_body->getLinearVelocity();
if(v.getZ() < - m_kart_properties->getSuspensionTravelCM()*0.01f*60)
if(v.getY() < - m_kart_properties->getSuspensionTravelCM()*0.01f*60)
{
Vec3 v_clamped = v;
// clamp the speed to 99% of the maxium falling speed.
v_clamped.setZ(-m_kart_properties->getSuspensionTravelCM()*0.01f*60 * 0.99f);
v_clamped.setY(-m_kart_properties->getSuspensionTravelCM()*0.01f*60 * 0.99f);
m_body->setLinearVelocity(v_clamped);
}
@ -1313,7 +1304,7 @@ void Kart::endRescue()
void Kart::loadData()
{
m_kart_properties->getKartModel()->attachModel(&m_animated_node);
m_kart_properties->getKartModel()->attachModel(&m_node);
createPhysics();
// Attach Particle System
@ -1326,9 +1317,9 @@ void Kart::loadData()
m_skidmarks = new SkidMarks(*this);
m_shadow = new Shadow(m_kart_properties->getShadowTexture(),
m_animated_node);
m_node);
m_stars_effect = new Stars(m_animated_node);
m_stars_effect = new Stars(m_node);
} // loadData
//-----------------------------------------------------------------------------
@ -1374,32 +1365,42 @@ void Kart::applyEngineForce(float force)
} // applyEngineForce
//-----------------------------------------------------------------------------
void Kart::updateGraphics(const Vec3& off_xyz, const Vec3& off_hpr)
void Kart::updateGraphics(const Vec3& offset_xyz,
const btQuaternion& rotation)
/** Updates the graphics model. Mainly set the graphical position to be the
* same as the physics position, but uses offsets to position and rotation
* for special gfx effects (e.g. skidding will turn the karts more). These
* variables are actually not used here atm, but are defined here and then
* used in Moveable.
* \param offset_xyz Offset to be added to the position.
* \param rotation Additional rotation.
*/
{
float wheel_z_axis[4];
float wheel_up_axis[4];
KartModel *kart_model = m_kart_properties->getKartModel();
for(unsigned int i=0; i<4; i++)
{
// Set the suspension length
wheel_z_axis[i] = m_default_suspension_length[i]
- m_vehicle->getWheelInfo(i).m_raycastInfo.m_suspensionLength;
wheel_up_axis[i] = m_default_suspension_length[i]
- m_vehicle->getWheelInfo(i).m_raycastInfo.m_suspensionLength;
}
#define AUTO_SKID_VISUAL 1.7f
const float auto_skid_visual=1.7f;
float auto_skid;
if (m_skidding>AUTO_SKID_VISUAL) // Above a limit, start counter rotating the wheels to get drifting look
auto_skid = m_controls.m_steer*30.0f*((AUTO_SKID_VISUAL - m_skidding) / 0.8f); // divisor comes from max_skid - AUTO_SKID_VISUAL
else
// FIXME
// if (m_skidding>auto_skid_visual) // Above a limit, start counter rotating the wheels to get drifting look
// auto_skid = m_controls.m_steer*30.0f*((auto_skid_visual - m_skidding) / 0.8f); // divisor comes from max_skid - AUTO_SKID_VISUAL
// else
auto_skid = m_controls.m_steer*30.0f;
kart_model->update(m_wheel_rotation, auto_skid,
getSteerPercent(), wheel_z_axis);
getSteerPercent(), wheel_up_axis);
Vec3 center_shift = getGravityCenterShift();
float X = m_vehicle->getWheelInfo(0).m_chassisConnectionPointCS.getZ()
float y = m_vehicle->getWheelInfo(0).m_chassisConnectionPointCS.getY()
- m_default_suspension_length[0]
- m_vehicle->getWheelInfo(0).m_wheelsRadius
- (kart_model->getWheelGraphicsRadius(0)
-kart_model->getWheelGraphicsPosition(0).getZ() );
center_shift.setZ(X);
-kart_model->getWheelGraphicsPosition(0).getY() );
center_shift.setY(y);
if(m_smoke_system)
{
@ -1425,7 +1426,8 @@ void Kart::updateGraphics(const Vec3& off_xyz, const Vec3& off_hpr)
float speed_ratio = getSpeed()/getMaxSpeed();
float offset_heading = getSteerPercent()*m_kart_properties->getSkidVisual()
* speed_ratio * m_skidding*m_skidding;
Moveable::updateGraphics(center_shift, Vec3(offset_heading, 0, 0));
Moveable::updateGraphics(center_shift,
btQuaternion(offset_heading, 0, 0));
} // updateGraphics
/* EOF */

View File

@ -204,7 +204,8 @@ public:
unsigned int getWorldKartId() const { return m_world_kart_id; }
void setWorldKartId(unsigned int n) { m_world_kart_id=n; }
void loadData();
virtual void updateGraphics(const Vec3& off_xyz, const Vec3& off_hpr);
virtual void updateGraphics(const Vec3& off_xyz,
const btQuaternion& off_rotation);
const KartProperties*
getKartProperties() const { return m_kart_properties; }
// ------------------------------------------------------------------------
@ -272,7 +273,6 @@ public:
/** Returns true if this kart has finished the race. */
bool hasFinishedRace () const { return m_finished_race; }
void endRescue ();
void getClosestKart (float *cdist, int *closest);
bool hasViewBlockedByPlunger() const
{ return m_view_blocked_by_plunger > 0; }

View File

@ -84,9 +84,10 @@ KartModel::~KartModel()
/** Attach the kart model and wheels to the scene node.
* \param node Node to attach the models to.
*/
void KartModel::attachModel(scene::IAnimatedMeshSceneNode **node)
void KartModel::attachModel(scene::ISceneNode **node)
{
m_node = *node = irr_driver->addAnimatedMesh(m_mesh);
*node = irr_driver->addAnimatedMesh(m_mesh);
m_node = static_cast<scene::IAnimatedMeshSceneNode*>(*node);
m_node->setAnimationSpeed(1500);
m_node->setLoopMode(false);
for(unsigned int i=0; i<4; i++)
@ -109,8 +110,8 @@ void KartModel::loadModels(const KartProperties &kart_properties)
Vec3 size = max-min;
m_z_offset = min.getZ();
m_kart_width = size.getX();
m_kart_height = size.getZ();
m_kart_length = size.getY();
m_kart_height = size.getY();
m_kart_length = size.getZ();
// FIXME: How do we handle this? it's a mesh only, so we can't
// simply move it in a transform (unless we turn it into a scene
// node). m_z_offset should probably be made available to kart.
@ -127,9 +128,9 @@ void KartModel::loadModels(const KartProperties &kart_properties)
m_wheel_graphics_position[i].setX( ( i==1||i==3)
? -0.5f*m_kart_width
: 0.5f*m_kart_width );
m_wheel_graphics_position[i].setY( (i<2) ? 0.5f*m_kart_length
m_wheel_graphics_position[i].setY(0);
m_wheel_graphics_position[i].setZ( (i<2) ? 0.5f*m_kart_length
: -0.5f*m_kart_length);
m_wheel_graphics_position[i].setZ(0);
}
}
@ -198,13 +199,13 @@ void KartModel::setDefaultPhysicsPosition(const Vec3 &center_shift,
? -0.5f*m_kart_width
: 0.5f*m_kart_width
+center_shift.getX( ));
m_wheel_physics_position[i].setY( (0.5f*m_kart_length-wheel_radius)
* ( (i<2) ? 1 : -1)
+center_shift.getY());
// Set the connection point so that a maximum compressed wheel
// (susp. length=0) will still poke a little bit out under the
// kart
m_wheel_physics_position[i].setZ(wheel_radius-0.05f);
m_wheel_physics_position[i].setY(wheel_radius-0.05f);
m_wheel_physics_position[i].setZ( (0.5f*m_kart_length-wheel_radius)
* ( (i<2) ? 1 : -1)
+center_shift.getZ());
} // if physics position is not defined
}
@ -263,9 +264,8 @@ void KartModel::update(float rotation, float visual_steer,
clamped_suspension[i] = ratio*suspension_length;
} // for i<4
// core::vector3df wheel_rear (RAD_TO_DEGREE(-rotation), 0, 0);
core::vector3df wheel_rear (-rotation, 0, 0);
core::vector3df wheel_steer(0, -visual_steer, 0);
core::vector3df wheel_steer(0, visual_steer, 0);
core::vector3df wheel_front = wheel_rear+wheel_steer;
for(unsigned int i=0; i<4; i++)

View File

@ -115,7 +115,7 @@ public:
~KartModel();
void loadInfo(const lisp::Lisp* lisp);
void loadModels(const KartProperties &kart_properties);
void attachModel(scene::IAnimatedMeshSceneNode **node);
void attachModel(scene::ISceneNode **node);
scene::IAnimatedMesh* getModel() const { return m_mesh; }
scene::IMesh* getWheelModel(const int wheelID) const { return m_wheel_model[wheelID]; }

View File

@ -64,7 +64,7 @@ KartProperties::KartProperties(const std::string &filename) : m_icon_material(0)
m_wheel_radius = m_chassis_linear_damping =
m_chassis_angular_damping = m_suspension_rest =
m_max_speed_reverse_ratio = m_jump_velocity =
m_z_rescue_offset = m_upright_tolerance = m_collision_side_impulse =
m_vert_rescue_offset = m_upright_tolerance = m_collision_side_impulse =
m_upright_max_force = m_suspension_travel_cm =
m_track_connection_accel = m_min_speed_turn = m_angle_at_min =
m_max_speed_turn = m_angle_at_max =
@ -175,21 +175,21 @@ void KartProperties::load(const std::string &filename, const std::string &node)
if(m_gravity_center_shift.getX()==UNDEFINED)
{
m_gravity_center_shift.setX(0);
m_gravity_center_shift.setY(0);
// Default: center at the very bottom of the kart.
m_gravity_center_shift.setZ(m_kart_model.getHeight()*0.5f);
m_gravity_center_shift.setY(m_kart_model.getHeight()*0.5f);
m_gravity_center_shift.setZ(0);
}
m_kart_model.setDefaultPhysicsPosition(m_gravity_center_shift,
m_wheel_radius);
m_wheel_base = fabsf( m_kart_model.getWheelPhysicsPosition(0).getY()
-m_kart_model.getWheelPhysicsPosition(2).getY());
m_wheel_radius );
m_wheel_base = fabsf( m_kart_model.getWheelPhysicsPosition(0).getZ()
-m_kart_model.getWheelPhysicsPosition(2).getZ());
m_angle_at_min = asinf(m_wheel_base/m_min_radius);
m_angle_at_max = asinf(m_wheel_base/m_max_radius);
if(m_max_speed_turn == m_min_speed_turn)
m_speed_angle_increase = 0.0;
else
m_speed_angle_increase = (m_angle_at_min - m_angle_at_max)
/ (m_max_speed_turn - m_min_speed_turn);
/ (m_max_speed_turn - m_min_speed_turn);
// Useful when tweaking kart parameters
@ -313,14 +313,14 @@ void KartProperties::getAllData(const XMLNode * root)
//TODO: wheel width is not loaded, yet is listed as an attribute in the xml file after wheel-radius?
root->get("chassis-linear-damping", &m_chassis_linear_damping);
root->get("chassis-linear-damping", &m_chassis_linear_damping);
root->get("chassis-angular-damping", &m_chassis_angular_damping);
root->get("max-speed-reverse-ratio", &m_max_speed_reverse_ratio);
root->get("suspension-rest", &m_suspension_rest);
root->get("suspension-travel-cm", &m_suspension_travel_cm);
root->get("jump-velocity", &m_jump_velocity);
root->get("collision-side-impulse", &m_collision_side_impulse);
root->get("z-rescue-offset", &m_z_rescue_offset);
root->get("suspension-rest", &m_suspension_rest);
root->get("suspension-travel-cm", &m_suspension_travel_cm);
root->get("jump-velocity", &m_jump_velocity);
root->get("collision-side-impulse", &m_collision_side_impulse);
root->get("vert-rescue-offset", &m_vert_rescue_offset);
//TODO: wheel front right and wheel front left is not loaded, yet is listed as an attribute in the xml file after wheel-radius
//TODO: same goes for their rear equivalents
@ -443,7 +443,7 @@ void KartProperties::getAllData(const lisp::Lisp* lisp)
lisp->get("suspension-travel-cm", m_suspension_travel_cm );
lisp->get("collision-side-impulse", m_collision_side_impulse );
lisp->get("jump-velocity", m_jump_velocity );
lisp->get("z-rescue-offset", m_z_rescue_offset );
lisp->get("vert-rescue-offset", m_vert_rescue_offset );
lisp->get("upright-tolerance", m_upright_tolerance );
lisp->get("upright-max-force", m_upright_max_force );
lisp->get("track-connection-accel", m_track_connection_accel );
@ -540,7 +540,7 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_suspension_travel_cm, "suspension-travel-cm" );
CHECK_NEG(m_collision_side_impulse, "collision-side-impulse" );
CHECK_NEG(m_jump_velocity, "jump-velocity" );
CHECK_NEG(m_z_rescue_offset, "z-rescue-offset" );
CHECK_NEG(m_vert_rescue_offset, "vert-rescue-offset" );
CHECK_NEG(m_upright_tolerance, "upright-tolerance" );
CHECK_NEG(m_upright_max_force, "upright-max-force" );
CHECK_NEG(m_track_connection_accel, "track-connection-accel" );

View File

@ -130,8 +130,8 @@ private:
/** An additional artifical side-impulse that pushes the slower kart
* out of the way of the faster kart in case of a collision. */
float m_collision_side_impulse;
float m_jump_velocity; // z velocity set when jumping
float m_z_rescue_offset; // z offset after rescue
float m_jump_velocity; /**< Vertical velocity set when jumping. */
float m_vert_rescue_offset; /**< Vertical offset after rescue. */
float m_upright_tolerance;
float m_upright_max_force;
@ -230,7 +230,9 @@ public:
/** Returns the (artificial) collision side impulse this kart will apply
* to a slower kart in case of a collision. */
float getCollisionSideImpulse () const {return m_collision_side_impulse; }
float getZRescueOffset () const {return m_z_rescue_offset; }
/** Returns the vertical offset when rescuing karts to avoid karts being
* rescued in (or under) the track. */
float getVertRescueOffset () const {return m_vert_rescue_offset; }
float getUprightTolerance () const {return m_upright_tolerance; }
float getUprightMaxForce () const {return m_upright_max_force; }
float getTrackConnectionAccel () const {return m_track_connection_accel; }

View File

@ -32,9 +32,7 @@ Moveable::Moveable()
m_motion_state = 0;
m_first_time = true;
m_mesh = NULL;
m_animated_mesh = NULL;
m_node = NULL;
m_animated_node = NULL;
} // Moveable
//-----------------------------------------------------------------------------
@ -44,47 +42,38 @@ Moveable::~Moveable()
if(m_body) delete m_body;
if(m_motion_state) delete m_motion_state;
if(m_node) irr_driver->removeNode(m_node);
if(m_animated_node) irr_driver->removeNode(m_animated_node);
if(m_mesh) irr_driver->removeMesh(m_mesh);
if(m_animated_mesh) irr_driver->removeMesh(m_animated_mesh);
} // ~Moveable
//-----------------------------------------------------------------------------
/** Sets this model to be non-animated.
/** Sets the mesh for this model.
* \param n The scene node.
*/
void Moveable::setNode(scene::ISceneNode *n)
{
m_node = n;
m_animated_node = NULL;
} // setNode
//-----------------------------------------------------------------------------
/** Sets this model to be animated.
* \param n The animated scene node.
/** Updates the graphics model. Mainly set the graphical position to be the
* same as the physics position, but uses offsets to position and rotation
* for special gfx effects (e.g. skidding will turn the karts more).
* \param offset_xyz Offset to be added to the position.
* \param rotation Additional rotation.
*/
void Moveable::setAnimatedNode(scene::IAnimatedMeshSceneNode *n)
void Moveable::updateGraphics(const Vec3& offset_xyz,
const btQuaternion& rotation)
{
m_node = NULL;
m_animated_node = n;
} // setAnimatedNode
//-----------------------------------------------------------------------------
void Moveable::updateGraphics(const Vec3& off_xyz, const Vec3& off_hpr)
{
Vec3 xyz=getXYZ()+off_xyz;
Vec3 hpr=getHPR()+off_hpr;
//sgCoord c=Coord(xyz, hpr).toSgCoord();
if(m_node)
{
m_node->setPosition(xyz.toIrrVector());
m_node->setRotation(hpr.toIrrHPR());
}
else if(m_animated_node)
{
m_animated_node->setPosition(xyz.toIrrVector());
m_animated_node->setRotation(hpr.toIrrHPR());
}
#ifdef DEBUG_PRINT
printf("moveable: %f %f (%f %f)\n", getXYZ().getX(), getXYZ().getZ(),
off_xyz.getX(), off_xyz.getZ());
#endif
Vec3 xyz=getXYZ()+offset_xyz;
btQuaternion r_all = getRotation()*rotation;
Vec3 hpr;
hpr.setHPR(r_all);
m_node->setPosition(xyz.toIrrVector());
m_node->setRotation(hpr.toIrrHPR());
} // updateGraphics
//-----------------------------------------------------------------------------
@ -97,51 +86,31 @@ void Moveable::reset()
m_body->setAngularVelocity(btVector3(0, 0, 0));
m_body->setCenterOfMassTransform(m_transform);
}
if(m_node)
m_node->setVisible(true); // In case that the objects was eliminated
if(m_animated_node)
m_animated_node->setVisible(true);
m_node->setVisible(true); // In case that the objects was eliminated
Coord c(m_transform);
m_hpr = c.getHPR();
m_hpr.setHPR(m_transform.getRotation());
} // reset
//-----------------------------------------------------------------------------
void Moveable::update(float dt)
{
m_motion_state->getWorldTransform(m_transform);
m_velocityLC = getVelocity()*m_transform.getBasis();
// The following code would synchronise bullet to irrlicht rotations, but
// heading etc. might not be 'correct', e.g. a 180 degree heading rotation
// would be reported as 180 degree roll and pitch, and 0 degree heading.
// So to get heading, pitch etc. the way needed elsewhere (camera etc),
// we would still have to rotate unit vectors and compute heading etc.
// with atan.
//btQuaternion q = m_transform.getRotation();
//core::quaternion qirr(q.getX(), q.getZ(), q.getY(), -q.getW());
//core::vector3df r;
//qirr.toEuler(r);
// Note: toIrrHPR mixes the axis back etc., so the assignments below
// mean that getIrrHPR returns exactly (r.x,r.y,r.z)*RAD_TO_DEGREE
//m_hpr.setX(-r.Y);
//m_hpr.setY(-r.X);
//m_hpr.setZ(-r.Z);
m_velocityLC = getVelocity()*m_transform.getBasis();
m_hpr.setHPR(m_transform.getRotation());
Vec3 forw_vec = m_transform.getBasis().getColumn(0);
m_heading = -atan2f(forw_vec.getZ(), forw_vec.getX());
// The pitch in hpr is in between -pi and pi. But for the camera it
// must be restricted to -pi/2 and pi/2 - so recompute it by restricting
// y to positive values, i.e. no pitch of more than pi/2.
Vec3 up = getTrans().getBasis().getColumn(1);
m_pitch = atan2(up.getZ(), fabsf(up.getY()));
m_hpr.setHPR(m_transform.getBasis());
// roll is not set correctly, I assume due to a different HPR order.
// So we compute the proper roll (by taking the angle between the up
// vector and the rotated up vector).
Vec3 up(0,0,1);
Vec3 roll_vec = m_transform.getBasis()*up;
float roll = atan2(roll_vec.getX(), roll_vec.getZ());
m_hpr.setRoll(roll);
updateGraphics(Vec3(0,0,0), Vec3(0,0,0));
updateGraphics(Vec3(0,0,0), btQuaternion(0, 0, 0, 1));
m_first_time = false ;
} // update
//-----------------------------------------------------------------------------
void Moveable::createBody(float mass, btTransform& trans,
btCollisionShape *shape) {
@ -161,8 +130,7 @@ void Moveable::createBody(float mass, btTransform& trans,
// functions are not called correctly. So only init the pointer to zero.
m_user_pointer.zero();
m_body->setUserPointer(&m_user_pointer);
const btMatrix3x3& basis=m_body->getWorldTransform().getBasis();
m_hpr.setHPR(basis);
m_hpr.setHPR(m_body->getWorldTransform().getRotation());
} // createBody
//-----------------------------------------------------------------------------

View File

@ -40,17 +40,19 @@ class Material;
class Moveable
{
private:
btVector3 m_velocityLC; /**<Velocity in kart coordinates */
btTransform m_transform;
Vec3 m_hpr;
btVector3 m_velocityLC; /**<Velocity in kart coordinates. */
btTransform m_transform;
Vec3 m_hpr;
/** The heading in m_hpr is between -90 and 90 degrees only. The 'real'
* heading between -180 to 180 degrees is stored in this variable. */
float m_heading;
/** The pitch between -90 and 90 degrees. */
float m_pitch;
protected:
UserPointer m_user_pointer;
scene::IAnimatedMesh *m_animated_mesh;
scene::IMesh *m_mesh;
scene::ISceneNode *m_node;
scene::IAnimatedMeshSceneNode
*m_animated_node;
int m_first_time ;
btRigidBody *m_body;
KartMotionState *m_motion_state;
@ -58,19 +60,27 @@ protected:
public:
Moveable();
virtual ~Moveable();
/** Returns the scene node of this moveable. */
scene::ISceneNode
*getNode() const { return m_node ? m_node : m_animated_node; }
*getNode() const { return m_node; }
void setNode(scene::ISceneNode *n);
void setAnimatedNode(scene::IAnimatedMeshSceneNode *n);
virtual const btVector3
&getVelocity() const {return m_body->getLinearVelocity();}
const btVector3
&getVelocityLC() const {return m_velocityLC; }
virtual void setVelocity(const btVector3& v) {m_body->setLinearVelocity(v); }
const Vec3& getXYZ() const {return (Vec3&)m_transform.getOrigin();}
/** Return the rotation, but heading is restricted to -90 and 90 degrees. */
const Vec3& getHPR() const {return m_hpr; }
/** Returns the heading between -180 and 180 degrees. Note that using
* getHPR().getHeading() can result a different heading (e.g. a heading
* of 180 degrees is the same as a roll and pitch around 180).*/
float getHeading() const {return m_heading; }
/** Returns the pitch of the kart, restricted to between -90 and 90 degrees.
* Note that using getHPR().getPitch can result in a different value! */
float getPitch() const {return m_pitch; }
const btQuaternion
getRotation() const {return m_transform.getRotation(); }
getRotation() const {return m_transform.getRotation(); }
/** Sets the XYZ coordinates of the moveable. */
void setXYZ(const Vec3& a)
@ -95,7 +105,8 @@ public:
}
// ------------------------------------------------------------------------
virtual void handleZipper () {};
virtual void updateGraphics(const Vec3& off_xyz, const Vec3& off_hpr);
virtual void updateGraphics(const Vec3& off_xyz,
const btQuaternion& off_rotation);
virtual void reset();
virtual void update(float dt) ;
btRigidBody *getBody() const {return m_body; }

View File

@ -245,10 +245,6 @@ int handleCmdLine(int argc, char **argv)
{
UserConfigParams::m_track_debug=1;
}
else if(!strcmp(argv[i], "--bullet-debug"))
{
UserConfigParams::m_bullet_debug=1;
}
else if(!strcmp(argv[i], "--kartsize-debug"))
{
UserConfigParams::m_print_kart_sizes=true;
@ -443,10 +439,18 @@ int handleCmdLine(int argc, char **argv)
else if( sscanf(argv[i], "--history=%d", &n)==1)
{
history->doReplayHistory( (History::HistoryReplayMode)n);
// Force the no-start screen flag, since this initialises
// the player structures correctly.
UserConfigParams::m_no_start_screen = true;
}
else if( !strcmp(argv[i], "--history") )
{
history->doReplayHistory(History::HISTORY_POSITION);
// Force the no-start screen flag, since this initialises
// the player structures correctly.
UserConfigParams::m_no_start_screen = true;
}
else if( !strcmp(argv[i], "--item") && i+1<argc )
{

View File

@ -303,12 +303,20 @@ int LinearWorld::getSectorForKart(const int kart_id) const
} // getSectorForKart
//-----------------------------------------------------------------------------
/** Returns the distance the kart has travelled along the track since
* crossing the start line..
* \param kart_id Index of the kart.
*/
float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const
{
return m_kart_info[kart_id].m_curr_track_coords.getY();
return m_kart_info[kart_id].m_curr_track_coords.getZ();
} // getDistanceDownTrackForKart
//-----------------------------------------------------------------------------
/** Gets the distance of the kart from the center of the driveline. Positive
* is to the right of the center, negative values to the left.
* \param kart_id Index of kart.
*/
float LinearWorld::getDistanceToCenterForKart(const int kart_id) const
{
return m_kart_info[kart_id].m_curr_track_coords.getX();
@ -528,7 +536,7 @@ void LinearWorld::moveKartAfterRescue(Kart* kart, btRigidBody* body)
kart->setXYZ( m_track->trackToSpatial(info.m_track_sector) );
btQuaternion heading(btVector3(0.0f, 0.0f, 1.0f),
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(info.m_track_sector) );
kart->setRotation(heading);
@ -539,8 +547,8 @@ void LinearWorld::moveKartAfterRescue(Kart* kart, btRigidBody* body)
float epsilon = 0.5f * kart->getKartHeight();
btTransform pos;
pos.setOrigin(kart->getXYZ()+btVector3(0, 0, kart->getKartHeight() + epsilon));
pos.setRotation(btQuaternion(btVector3(0.0f, 0.0f, 1.0f),
pos.setOrigin(kart->getXYZ()+btVector3(0, kart->getKartHeight() + epsilon, 0));
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(info.m_track_sector)));
body->setCenterOfMassTransform(pos);
@ -551,9 +559,9 @@ void LinearWorld::moveKartAfterRescue(Kart* kart, btRigidBody* body)
if (kart_over_ground)
{
//add vertical offset so that the kart starts off above the track
float vertical_offset = kart->getKartProperties()->getZRescueOffset() *
float vertical_offset = kart->getKartProperties()->getVertRescueOffset() *
kart->getKartHeight();
body->translate(btVector3(0, 0, vertical_offset));
body->translate(btVector3(0, vertical_offset, 0));
}
else
{
@ -573,8 +581,9 @@ void LinearWorld::updateRacePosition()
#ifdef DEBUG
bool rank_used[kart_amount+1];
for (unsigned int n=0; n<=kart_amount; n++) rank_used[n] = false;
std::vector<bool> rank_used;
for (unsigned int n=0; n<=kart_amount; n++)
rank_used.push_back(false);
#endif
for (unsigned int i=0; i<kart_amount; i++)
@ -663,7 +672,7 @@ void LinearWorld::updateRacePosition()
sound_manager->switchToFastMusic();
m_faster_music_active=true;
}
}
} // for i<kart_amount
} // updateRacePosition
@ -688,7 +697,7 @@ void LinearWorld::checkForWrongDirection(unsigned int i)
return;
// check if the player is going in the wrong direction
float angle_diff = kart->getHPR().getHeading() -
float angle_diff = kart->getHeading() -
m_track->getAngle(m_kart_info[i].m_track_sector);
if(angle_diff > M_PI) angle_diff -= 2*M_PI;
else if (angle_diff < -M_PI) angle_diff += 2*M_PI;

View File

@ -252,18 +252,19 @@ void ThreeStrikesBattle::moveKartAfterRescue(Kart* kart, btRigidBody* body)
const int start_spots_amount = world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0);
int smallest_distance_found = -1, closest_id_found = -1;
float smallest_distance_found = -1;
int closest_id_found = -1;
const int kart_x = (int)(kart->getXYZ()[0]);
const int kart_y = (int)(kart->getXYZ()[1]);
const float kart_x = kart->getXYZ().getX();
const float kart_z = kart->getXYZ().getZ();
for(int n=0; n<start_spots_amount; n++)
{
// no need for the overhead to compute exact distance with sqrt(), so using the
// 'manhattan' heuristic which will do fine enough.
const Vec3 &v=world->getTrack()->getStartPosition(n);
const int dist_n = abs((int)(kart_x - v.getX())) +
abs((int)(kart_y - v.getY()));
const float dist_n= fabs(kart_x - v.getX()) +
fabs(kart_z - v.getZ());
if(dist_n < smallest_distance_found || closest_id_found == -1)
{
closest_id_found = n;
@ -276,14 +277,14 @@ void ThreeStrikesBattle::moveKartAfterRescue(Kart* kart, btRigidBody* body)
kart->setXYZ( Vec3(v) );
// FIXME - implement correct heading
btQuaternion heading(btVector3(0.0f, 0.0f, 1.0f),
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
world->getTrack()->getStartHeading(closest_id_found));
kart->setRotation(heading);
//position kart from same height as in World::resetAllKarts
btTransform pos;
pos.setOrigin(kart->getXYZ()+btVector3(0, 0, 0.5f*kart->getKartHeight()));
pos.setRotation( btQuaternion(btVector3(0.0f, 0.0f, 1.0f), 0 /* angle */) );
pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f));
pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) );
body->setCenterOfMassTransform(pos);
@ -293,9 +294,9 @@ void ThreeStrikesBattle::moveKartAfterRescue(Kart* kart, btRigidBody* body)
if (kart_over_ground)
{
//add vertical offset so that the kart starts off above the track
float vertical_offset = kart->getKartProperties()->getZRescueOffset() *
float vertical_offset = kart->getKartProperties()->getVertRescueOffset() *
kart->getKartHeight();
body->translate(btVector3(0, 0, vertical_offset));
body->translate(btVector3(0, vertical_offset, 0));
}
else
{

View File

@ -312,7 +312,7 @@ void World::resetAllKarts()
for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++)
{
///start projection from top of kart
btVector3 up_offset(0, 0, 0.5f * ((*i)->getKartHeight()));
btVector3 up_offset(0, 0.5f * ((*i)->getKartHeight()), 0);
(*i)->getVehicle()->getRigidBody()->translate (up_offset);
bool kart_over_ground = m_physics->projectKartDownwards(*i);

View File

@ -754,7 +754,7 @@ void btKart::updateFriction(btScalar timeStep)
btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
rel_pos[2] *= wheelInfo.m_rollInfluence;
rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
m_chassisBody->applyImpulse(sideImp,rel_pos);
//apply friction impulse on the ground

View File

@ -23,6 +23,8 @@ subject to the following restrictions:
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
#include "karts/kart.hpp"
//!
//!
//!
@ -83,29 +85,31 @@ void btUprightConstraint::solveAngularLimit(
btVector3 motorImp = clippedMotorImpulse * limit->m_axis;
body0->applyTorqueImpulse(motorImp);
}
} // solveAngularLimit
//!
//!
//!
btUprightConstraint::btUprightConstraint(btRigidBody& rbA, const btTransform& frameInA )
: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA)
, m_frameInA(frameInA)
btUprightConstraint::btUprightConstraint(const Kart* kart,
const btTransform& frameInA)
: btTypedConstraint(D6_CONSTRAINT_TYPE, *(kart->getBody()))
, m_frameInA(frameInA)
{
m_ERP = 1.0f;
m_bounce = 0.0f;
m_damping = 1.0f;
m_limitSoftness = 1.0f;
m_maxLimitForce = 3000.0f;
m_disable_time = 0.0f;
m_limit[0].m_accumulatedImpulse = 0.0f;
m_limit[1].m_accumulatedImpulse = 0.0f;
m_limit[ 0 ].m_axis = btVector3( 1, 0, 0 );
m_limit[ 1 ].m_axis = btVector3( 0, 1, 0 );
setLimit( SIMD_PI * 0.4f );
}
m_kart = kart;
m_ERP = 1.0f;
m_bounce = 0.0f;
m_damping = 1.0f;
m_limitSoftness = 1.0f;
m_maxLimitForce = 3000.0f;
m_disable_time = 0.0f;
m_limit[0].m_accumulatedImpulse = 0.0f;
m_limit[1].m_accumulatedImpulse = 0.0f;
m_limit[ 0 ].m_axis = btVector3( 1, 0, 0 );
m_limit[ 1 ].m_axis = btVector3( 0, 1, 0 );
setLimit( SIMD_PI * 0.4f );
} // btUprightConstraint
//!
//!
@ -113,31 +117,26 @@ btUprightConstraint::btUprightConstraint(btRigidBody& rbA, const btTransform& fr
void btUprightConstraint::buildJacobian()
{
btTransform worldTransform = m_rbA.getCenterOfMassTransform() * m_frameInA;
btVector3 upAxis = worldTransform.getBasis().getColumn(2);
m_limit[ 0 ].m_angle = btAtan2( upAxis.getZ(), upAxis.getY() )-SIMD_PI/2.0f;
m_limit[ 1 ].m_angle = -btAtan2( upAxis.getZ(), upAxis.getX() )+SIMD_PI/2.0f;
btTransform worldTransform = m_rbA.getCenterOfMassTransform() * m_frameInA;
btVector3 upAxis = worldTransform.getBasis().getColumn(2);
m_limit[ 0 ].m_angle = m_kart->getPitch();
m_limit[ 1 ].m_angle = m_kart->getHPR().getRoll();
for ( int i = 0; i < 2; i++ )
{
if ( m_limit[ i ].m_angle < -SIMD_PI )
m_limit[ i ].m_angle += 2 * SIMD_PI;
if ( m_limit[ i ].m_angle > SIMD_PI )
m_limit[ i ].m_angle -= 2 * SIMD_PI;
new (&m_jacAng[ i ]) btJacobianEntry( m_limit[ i ].m_axis,
m_rbA.getCenterOfMassTransform().getBasis().transpose(),
m_rbB.getCenterOfMassTransform().getBasis().transpose(),
m_rbA.getInvInertiaDiagLocal(),
m_rbB.getInvInertiaDiagLocal());
}
}
for ( int i = 0; i < 2; i++ )
{
new (&m_jacAng[ i ]) btJacobianEntry( m_limit[ i ].m_axis,
m_rbA.getCenterOfMassTransform().getBasis().transpose(),
m_rbB.getCenterOfMassTransform().getBasis().transpose(),
m_rbA.getInvInertiaDiagLocal(),
m_rbB.getInvInertiaDiagLocal());
}
} // buildJacobian
//!
//!
//!
void btUprightConstraint::solveConstraint(btScalar timeStep)
void btUprightConstraint::solveConstraint(btScalar timeStep)
{
m_timeStep = timeStep;
@ -150,5 +149,5 @@ void btUprightConstraint::solveConstraint(btScalar timeStep)
solveAngularLimit( &m_limit[ 0 ], m_timeStep, btScalar(1.) / m_jacAng[ 0 ].getDiagonal(), &m_rbA );
solveAngularLimit( &m_limit[ 1 ], m_timeStep, btScalar(1.) / m_jacAng[ 1 ].getDiagonal(), &m_rbA );
}
} // solveConstraint

View File

@ -22,35 +22,33 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
class btRigidBody;
class Kart;
//!
//!
//!
class btUprightConstraintLimit
{
public:
btVector3 m_axis;
btScalar m_angle;
btScalar m_accumulatedImpulse;
btScalar m_currentLimitError;
};
class btUprightConstraint : public btTypedConstraint
{
protected:
private:
class btUprightConstraintLimit
{
public:
btVector3 m_axis;
btScalar m_angle;
btScalar m_accumulatedImpulse;
btScalar m_currentLimitError;
};
//! relative_frames
//!@{
btTransform m_frameInA;//!< the constraint space w.r.t body A
btTransform m_frameInA;//!< the constraint space w.r.t body A
//!@}
//! Jacobians
//!@{
btJacobianEntry m_jacAng[ 2 ];//!< angular constraint
btJacobianEntry m_jacAng[ 2 ];//!< angular constraint
//!@}
const Kart *m_kart;
protected:
//! temporal variables
@ -61,71 +59,47 @@ protected:
btScalar m_damping;
btScalar m_maxLimitForce;
btScalar m_limitSoftness;
btScalar m_hiLimit;
btScalar m_loLimit;
btScalar m_disable_time;
btScalar m_hiLimit;
btScalar m_loLimit;
btScalar m_disable_time;
btUprightConstraintLimit m_limit[ 2 ];
//!@}
btUprightConstraint& operator=(btUprightConstraint& other)
btUprightConstraint& operator=(btUprightConstraint& other)
{
btAssert(0);
(void) other;
return *this;
}
void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW);
void buildAngularJacobian(btJacobianEntry & jacAngular,
const btVector3 & jointAxisW);
void solveAngularLimit(
btUprightConstraintLimit *limit,
btScalar timeStep, btScalar jacDiagABInv,
btRigidBody * body0 );
void solveAngularLimit(btUprightConstraintLimit *limit,
btScalar timeStep, btScalar jacDiagABInv,
btRigidBody * body0 );
public:
btUprightConstraint(btRigidBody& rbA, const btTransform& frameInA );
// -PI,+PI is the full range
// 0,0 is no rotation around x or z
// -PI*0.2,+PI*0.2 is a nice bit of tilt
void setLimit( btScalar range )
{
m_loLimit = -range;
m_hiLimit = +range;
}
// Error correction scaling
// 0 - 1
//
void setErp( btScalar erp )
{
m_ERP = erp;
}
void setBounce( btScalar bounce )
{
m_bounce = bounce;
}
void setMaxLimitForce( btScalar force )
{
m_maxLimitForce = force;
}
void setLimitSoftness( btScalar softness )
{
m_limitSoftness = softness;
}
void setDamping( btScalar damping )
{
m_damping = damping;
}
void setDisableTime( btScalar t )
{
m_disable_time = t;
}
btUprightConstraint(const Kart* kart, const btTransform& frameInA);
// -PI,+PI is the full range
// 0,0 is no rotation around x or z
// -PI*0.2,+PI*0.2 is a nice bit of tilt
void setLimit( btScalar range ) { m_loLimit = -range;
m_hiLimit = +range; }
// Error correction scaling
// 0 - 1
void setErp( btScalar erp ) { m_ERP = erp; }
void setBounce( btScalar bounce ) { m_bounce = bounce; }
void setMaxLimitForce( btScalar force ) { m_maxLimitForce = force; }
void setLimitSoftness( btScalar softness ) { m_limitSoftness = softness; }
void setDamping( btScalar damping ) { m_damping = damping; }
void setDisableTime( btScalar t ) { m_disable_time = t; }
virtual void buildJacobian();
virtual void solveConstraint(btScalar timeStep);
virtual void solveConstraint(btScalar timeStep);
};

View File

@ -23,48 +23,34 @@
IrrDebugDrawer::IrrDebugDrawer()
{
m_debug_mode = DBG_DrawAabb;
m_debug_mode = DM_NONE;
} // IrrDebugDrawer
// -----------------------------------------------------------------------------
/** Activates the debug view. It makes all karts invisible (in irrlicht), so
* that the bullet view can be seen.
/** Activates the next debug mode, or switches the mode off again.
*/
void IrrDebugDrawer::activate()
void IrrDebugDrawer::nextDebugMode()
{
// Go to next debug mode. Note that debug mode 3 (
m_debug_mode = (DebugModeType) ((m_debug_mode+1) % 3);
World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
for(unsigned int i=0; i<num_karts; i++)
{
Kart *kart = world->getKart(i);
if(kart->isEliminated()) continue;
kart->getNode()->setVisible(false);
kart->getNode()->setVisible(!(m_debug_mode & DM_NO_KARTS_GRAPHICS));
}
} // activate
// -----------------------------------------------------------------------------
/** Deactivates the bullet debug view, and makes all karts visible again.
*/
void IrrDebugDrawer::deactivate()
{
World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
for(unsigned int i=0; i<num_karts; i++)
{
Kart *kart = world->getKart(i);
if(kart->isEliminated()) continue;
kart->getNode()->setVisible(true);
}
} // deactivate
} // nextDebugMode
// -----------------------------------------------------------------------------
void IrrDebugDrawer::drawLine(const btVector3& from, const btVector3& to,
const btVector3& color)
{
Vec3 f(from);
Vec3 t(to);
video::SColor c(255, (int)(color.getX()*255), (int)(color.getY()*255),
(int)(color.getZ()*255) );
irr_driver->getVideoDriver()->draw3DLine(f.toIrrVector(),
t.toIrrVector(), c);
irr_driver->getVideoDriver()->draw3DLine((const core::vector3df&)from,
(const core::vector3df&)to, c);
}
/* EOF */

View File

@ -30,9 +30,18 @@ using namespace irr;
class IrrDebugDrawer : public btIDebugDraw
{
/** The drawing mode to use. */
int m_debug_mode;
/** The drawing mode to use:
* If bit 0 is set, draw the bullet collision shape of karts
* If bit 1 is set, don't draw the kart graphics
*/
enum DebugModeType { DM_NONE = 0x00,
DM_KARTS_PHYSICS = 0x01,
DM_NO_KARTS_GRAPHICS = 0x02
};
DebugModeType m_debug_mode;
protected:
virtual void setDebugMode(int debug_mode) {}
virtual int getDebugMode() const { return DBG_DrawWireframe;}
public:
IrrDebugDrawer();
void render(float dt);
@ -47,11 +56,9 @@ public:
virtual void reportErrorWarning(const char* warningString) {}
virtual void draw3dText(const btVector3& location,
const char* textString) {}
virtual void setDebugMode(int debug_mode) { m_debug_mode = debug_mode; }
virtual int getDebugMode() const { return m_debug_mode; }
void activate();
void deactivate();
/** Returns true if debug mode is enabled. */
bool debugEnabled() const {return m_debug_mode!=0;}
void nextDebugMode();
}; // IrrDebugDrawer
#endif

View File

@ -45,20 +45,20 @@ 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,
m_axis_sweep,
this,
m_collision_conf);
m_dynamics_world->setGravity(btVector3(0.0f, 0.0f,
-World::getWorld()->getTrack()->getGravity()));
m_dynamics_world->setGravity(btVector3(0.0f,
-World::getWorld()->getTrack()->getGravity(),
0.0f));
m_debug_drawer = new IrrDebugDrawer();
m_debug_drawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
m_dynamics_world->setDebugDrawer(m_debug_drawer);
} // init
//-----------------------------------------------------------------------------
Physics::~Physics()
{
if(UserConfigParams::m_bullet_debug) delete m_debug_drawer;
delete m_debug_drawer;
delete m_dynamics_world;
delete m_axis_sweep;
delete m_dispatcher;
@ -153,7 +153,7 @@ void Physics::update(float dt)
bool Physics::projectKartDownwards(const Kart *k)
{
btVector3 hell(0, 0, -10000);
btVector3 hell(0, -10000, 0);
return k->getVehicle()->projectVehicleToSurface(hell, true /*allow translation*/);
} //projectKartsDownwards
@ -343,6 +343,9 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
/** A debug draw function to show the track and all karts. */
void Physics::draw()
{
if(!m_debug_drawer->debugEnabled() ||
!World::getWorld()->isRacePhase()) return;
video::SColor color(77,179,0,0);
video::SMaterial material;
material.Thickness = 2;

View File

@ -101,11 +101,11 @@ public:
void draw ();
btDynamicsWorld*
getPhysicsWorld () const {return m_dynamics_world;}
void debugDraw (float m[16], btCollisionShape *s, const btVector3 color);
/** Activates the debug drawer. */
void activateDebug () {m_debug_drawer->activate(); }
/** Deactivates the debug drawer. */
void deactivateDebug () {m_debug_drawer->deactivate(); }
/** Activates the next debug mode (or switches it off again).
*/
void nextDebugMode () {m_debug_drawer->nextDebugMode(); }
/** Returns true if the debug drawer is enabled. */
bool isDebug() const {return m_debug_drawer->debugEnabled(); }
bool projectKartDownwards(const Kart *k);
virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies,
btPersistentManifold** manifold,int numManifolds,

View File

@ -28,6 +28,8 @@
History* history = 0;
#define KEEP_OLD_FORMAT
//-----------------------------------------------------------------------------
/** Initialises the history object and sets the mode to none.
*/
@ -64,7 +66,7 @@ void History::initRecording()
void History::allocateMemory(int number_of_frames)
{
m_all_deltas.resize (number_of_frames);
unsigned int num_karts = World::getWorld()->getNumKarts();
unsigned int num_karts = race_manager->getNumberOfKarts();
m_all_controls.resize (number_of_frames*num_karts);
m_all_xyz.resize (number_of_frames*num_karts);
m_all_rotations.resize(number_of_frames*num_karts);
@ -186,8 +188,12 @@ void History::Save()
m_all_controls[j].m_steer,
m_all_controls[j].m_accel,
m_all_controls[j].getButtonsCompressed(),
m_all_xyz[j].getX(), m_all_xyz[j].getY(),
m_all_xyz[j].getZ(),
m_all_xyz[j].getX(),
#ifdef KEEP_OLD_FORMAT
m_all_xyz[j].getZ(), m_all_xyz[j].getY(),
#else
m_all_xyz[j].getY(), m_all_xyz[j].getZ(),
#endif
m_all_rotations[j].getX(), m_all_rotations[j].getY(),
m_all_rotations[j].getZ(), m_all_rotations[j].getW() );
j=(j+1)%m_size;
@ -297,7 +303,18 @@ void History::Load()
&m_all_controls[i].m_steer,
&m_all_controls[i].m_accel,
&buttonsCompressed,
&x, &y, &z, &rx, &ry, &rz, &rw);
&x,
#ifdef KEEP_OLD_FORMAT
&z, &y,
//xyz
//yxz
//yzx
&rx, &rz, &ry, &rw
#else
&y, &z,
&rx, &ry, &rz, &rw
#endif
);
m_all_xyz[i] = Vec3(x,y,z);
m_all_rotations[i] = btQuaternion(rx,ry,rz,rw);
m_all_controls[i].setButtonsCompressed(char(buttonsCompressed));

View File

@ -661,7 +661,7 @@ public:
// Random kart
scene::IMesh* model = item_manager->getItemModel(Item::ITEM_BONUS_BOX);
w3->clearModels();
w3->addModel( model, Vec3(0.0f, 0.0f, -12.0f) );
w3->addModel( model, Vec3(0.0f, -12.0f, 0.0f) );
w3->update(0);
m_parent->m_kart_widgets[playerID].kartName->setText( _("Random Kart") );
}

View File

@ -60,7 +60,7 @@ void CheckLine::reset(const Track &track)
Vec3 CheckLine::getCenterPoint() const
{
core::vector2df c=m_line.getMiddle();
Vec3 xyz(c.X, c.Y, m_min_height);
Vec3 xyz(c.X, m_min_height, c.Y);
return xyz;
} // getCenterPoint
@ -89,8 +89,8 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx)
// between -1 and 4 units (negative numbers are unlikely, but help
// in case that there is 'somewhat' inside of the track, or the
// checklines are a bit off in Z direction.
result = new_pos.getZ()-m_min_height<4.0f &&
new_pos.getZ()-m_min_height>-1.0f;
result = new_pos.getY()-m_min_height<4.0f &&
new_pos.getY()-m_min_height>-1.0f;
}
else
result = false;

View File

@ -52,10 +52,10 @@ GraphNode::GraphNode(unsigned int index)
+ (quad[3]-quad[2]).length() ) * 0.5f;
Vec3 lower = (quad[0]+quad[1]) * 0.5f;
Vec3 upper = (quad[2]+quad[3]) * 0.5f;
m_line = core::line2df(lower.getX(), lower.getY(),
upper.getX(), upper.getY() );
m_line = core::line2df(lower.getX(), lower.getZ(),
upper.getX(), upper.getZ() );
// Only this 2d point is needed later
m_lower_center = core::vector2df(lower.getX(), lower.getY());
m_lower_center = core::vector2df(lower.getX(), lower.getZ());
} // GraphNode
// ----------------------------------------------------------------------------
@ -76,7 +76,7 @@ void GraphNode::addSuccessor(unsigned int to)
Vec3 diff = next_quad.getCenter() - this_quad.getCenter();
m_distance_to_next.push_back(d2.getLength());
float theta = -atan2(diff.getX(), diff.getY());
float theta = atan2(diff.getX(), diff.getZ());
m_angle_to_next.push_back(theta);
// The length of this quad is the average of the left and right side
@ -103,15 +103,15 @@ void GraphNode::addSuccessor(unsigned int to)
* is it. All these computations are done in 2D only.
* \param xyz The coordinates of the point.
* \param result The X coordinate contains the sidewards distance, the
* y coordinate the forward distance.
* Z coordinate the forward distance.
*/
void GraphNode::getDistances(const Vec3 &xyz, Vec3 *result)
{
core::vector2df xyz2d(xyz.getX(), xyz.getY());
core::vector2df xyz2d(xyz.getX(), xyz.getZ());
core::vector2df closest = m_line.getClosestPoint(xyz2d);
if(m_line.getPointOrientation(xyz2d)>0)
result->setX( (closest-xyz2d).getLength()); // to the right
else
result->setX(-(closest-xyz2d).getLength()); // to the left
result->setY( m_distance_from_start + (closest-m_lower_center).getLength());
result->setZ( m_distance_from_start + (closest-m_lower_center).getLength());
} // getDistances

View File

@ -41,8 +41,8 @@ Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
m_p[0]=p0; m_p[1]=p1; m_p[2]=p2; m_p[3]=p3;
}
m_center = 0.25f*(p0+p1+p2+p3);
m_min_height = std::min ( std::min(p0.getZ(), p1.getZ()),
std::min(p0.getZ(), p1.getZ()) );
m_min_height = std::min ( std::min(p0.getY(), p1.getY()),
std::min(p0.getY(), p1.getY()) );
m_invisible = invisible;
} // Quad
@ -87,8 +87,8 @@ void Quad::getVertices(video::S3DVertex *v, const video::SColor &color) const
*/
float Quad::sideOfLine2D(const Vec3& l1, const Vec3& l2, const Vec3& p) const
{
return (l2.getX()-l1.getX())*(p.getY()-l1.getY()) -
(l2.getY()-l1.getY())*(p.getX()-l1.getX());
return (l2.getX()-l1.getX())*(p.getZ()-l1.getZ()) -
(l2.getZ()-l1.getZ())*(p.getX()-l1.getX());
} // sideOfLine
// ----------------------------------------------------------------------------
@ -102,6 +102,7 @@ bool Quad::pointInQuad(const Vec3& p) const
sideOfLine2D(m_p[3], m_p[0], p) >= 0.0;
}
} // pointInQuad
// ----------------------------------------------------------------------------
/** Transforms a quad by a given transform (i.e. translation+rotation). This
* function does not modify this quad, the results are stored in the quad

View File

@ -79,7 +79,7 @@ void QuadGraph::setStartCoordinate(const CheckLine &cl)
}
Vec3 xyz;
spatialToTrack(&xyz, start_point, sector);
m_offset_for_startline = xyz.getY();
m_offset_for_startline = xyz.getZ();
} // setStartCoordinate
// -----------------------------------------------------------------------------
@ -311,7 +311,7 @@ void QuadGraph::getSuccessors(int node_number, std::vector<unsigned int>& succ)
* of the returned vector is how much of the track the point has gone
* through, the x-axis is on which side of the road it is. The Z axis
* is not changed.
* \param dst Returns the results in the X and Y coordinates.
* \param dst Returns the results in the X and Z coordinates.
* \param xyz The position of the kart.
* \param sector The graph node the position is on.
*/
@ -325,10 +325,10 @@ void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
}
getNode(sector).getDistances(xyz, dst);
float y=dst->getY();
y=y-m_offset_for_startline;
if(y<0) y+=m_lap_length;
dst->setY(y);
float z=dst->getZ();
z=z-m_offset_for_startline;
if(z<0) z+=m_lap_length;
dst->setZ(z);
} // spatialToTrack
//-----------------------------------------------------------------------------
@ -381,7 +381,7 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
else
indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0;
const Quad &q = getQuad(indx);
float dist = xyz.getZ() - q.getMinHeight();
float dist = xyz.getY() - q.getMinHeight();
// While negative distances are unlikely, we allow some small netative
// numbers in case that the kart is partly in the track.
if(q.pointInQuad(xyz) && dist < min_dist && dist>-1.0f)
@ -489,15 +489,15 @@ video::ITexture *QuadGraph::makeMiniMap(const core::dimension2du &dimension,
Vec3 center = (bb_max+bb_min)*0.5f;
core::matrix4 projection;
projection.buildProjectionMatrixOrthoLH(bb_max.getX()-bb_min.getX(),
bb_max.getY()-bb_min.getY(),
-1, bb_max.getZ()-bb_min.getZ()+1);
bb_max.getZ()-bb_min.getZ(),
-1, bb_max.getY()-bb_min.getY()+1);
camera->setProjectionMatrix(projection, true);
// Adjust z position by +1 for max, -1 for min - this helps in case that
// the maximum z coordinate is negative (otherwise the minimap is mirrored)
// and avoids problems for tracks which have a flat (max z = min z) minimap.
camera->setPosition(core::vector3df(center.getX(), bb_max.getZ()+1, center.getY()));
camera->setUpVector(core::vector3df(0,0,1));
camera->setTarget(core::vector3df(center.getX(),bb_min.getZ()-1,center.getY()));
camera->setPosition(core::vector3df(center.getX(), bb_max.getY()+1, center.getZ()));
camera->setUpVector(core::vector3df(0, 0, 1));
camera->setTarget(core::vector3df(center.getX(),bb_min.getY()-1,center.getZ()));
video::ITexture *texture = rttProvider.renderToTexture();
@ -505,7 +505,7 @@ video::ITexture *QuadGraph::makeMiniMap(const core::dimension2du &dimension,
irr_driver->removeCameraSceneNode(camera);
m_min_coord = bb_min;
m_scaling.setX(dimension.Width/(bb_max.getX()-bb_min.getX()));
m_scaling.setY(dimension.Width/(bb_max.getY()-bb_min.getY()));
m_scaling.setZ(dimension.Width/(bb_max.getZ()-bb_min.getZ()));
return texture;
} // drawMiniMap
@ -519,6 +519,6 @@ video::ITexture *QuadGraph::makeMiniMap(const core::dimension2du &dimension,
void QuadGraph::mapPoint2MiniMap(const Vec3 &xyz,Vec3 *draw_at) const
{
draw_at->setX((xyz.getX()-m_min_coord.getX())*m_scaling.getX());
draw_at->setY((xyz.getY()-m_min_coord.getY())*m_scaling.getY());
draw_at->setY((xyz.getZ()-m_min_coord.getZ())*m_scaling.getZ());
} // mapPoint

View File

@ -60,13 +60,13 @@ float TerrainInfo::getTerrainPitch(float heading) const {
if(m_HoT==Track::NOHIT) return 0.0f;
const float X =-sin(heading);
const float Y = cos(heading);
const float Z = cos(heading);
// Compute the angle between the normal of the plane and the line to
// (x,y,0). (x,y,0) is normalised, so are the coordinates of the plane,
// (x,0,z). (x,0,z) is normalised, so are the coordinates of the plane,
// simplifying the computation of the scalar product.
float pitch = ( m_normal.getX()*X + m_normal.getY()*Y ); // use ( x,y,0)
float pitch = ( m_normal.getX()*X + m_normal.getZ()*Z ); // use (x, 0, z)
// The actual angle computed above is between the normal and the (x,y,0)
// The actual angle computed above is between the normal and the (x, 0, z)
// line, so to compute the actual angles 90 degrees must be subtracted.
pitch = acosf(pitch) - NINETY_DEGREE_RAD;
return pitch;

View File

@ -166,7 +166,7 @@ btTransform Track::getStartTransform(unsigned int pos) const
Vec3 orig = pos<m_start_positions.size()
? m_start_positions[pos]
: Vec3( (pos%2==0)?1.5f:-1.5f, -1.5f*pos-1.5f, 1.0f);
: Vec3( (pos%2==0)?1.5f:-1.5f, 1.0f, -1.5f*pos-1.5f);
btTransform start;
start.setOrigin(orig);
start.setRotation(btQuaternion(btVector3(0, 0, 1),
@ -391,7 +391,7 @@ void Track::convertTrackToBullet(const scene::IMesh *mesh,
int indx=mbIndices[j+k];
core::vector3df v = mbVertices[indx].Pos;
mat.transformVect(v);
vertices[k] = Vec3(v);
vertices[k]=v;
} // for k
if(tmesh) tmesh->addTriangle(vertices[0], vertices[1],
vertices[2], material );
@ -703,7 +703,7 @@ void Track::loadTrackModel(unsigned int mode_id)
// Set some kind of default in case Z is not defined in the file
// (with the new track exporter it always is defined anyway).
// Z is the height from which the item is dropped on the track.
xyz.setZ(1000);
xyz.setY(1000);
node->getXYZ(&xyz);
bool drop=true;
node->get("drop", &drop);
@ -884,14 +884,14 @@ void Track::itemCommand(const Vec3 &xyz, Item::ItemType type,
// if only 2d coordinates are given, let the item fall from very high
if(drop)
{
loc.setZ(getTerrainHeight(loc));
loc.setY(getTerrainHeight(loc));
}
// Don't tilt the items, since otherwise the rotation will look odd,
// i.e. the items will not rotate around the normal, but 'wobble'
// around.
//Vec3 normal(0.7071f, 0, 0.7071f);
Vec3 normal(0, 0, 1);
Vec3 normal(0, 1, 0);
item_manager->newItem(type, loc, normal);
} // itemCommand
@ -900,7 +900,7 @@ void Track::getTerrainInfo(const Vec3 &pos, float *hot, Vec3 *normal,
const Material **material) const
{
btVector3 to_pos(pos);
to_pos.setZ(-100000.f);
to_pos.setY(-100000.f);
class MaterialCollision : public btCollisionWorld::ClosestRayResultCallback
{
@ -938,7 +938,7 @@ void Track::getTerrainInfo(const Vec3 &pos, float *hot, Vec3 *normal,
return;
}
*hot = rayCallback.m_hitPointWorld.getZ();
*hot = rayCallback.m_hitPointWorld.getY();
*normal = rayCallback.m_hitNormalWorld;
*material = rayCallback.m_material;
// Note: material might be NULL. This happens if the ray cast does not

View File

@ -56,7 +56,7 @@ public:
Coord(const btTransform& t)
{
m_xyz = t.getOrigin();
m_hpr.setHPR(t.getBasis());
m_hpr.setHPR(t.getRotation());
//setSgCoord();
} // Coord
// ------------------------------------------------------------------------

View File

@ -21,59 +21,22 @@
#include "utils/constants.hpp"
void Vec3::setHPR(const btMatrix3x3& m)
void Vec3::setHPR(const btQuaternion& q)
{
float f[4][4];
m.getOpenGLSubMatrix((float*)f);
float W = q.getW();
float X = q.getX();
float Y = q.getY();
float Z = q.getZ();
float WSquared = W * W;
float XSquared = X * X;
float YSquared = Y * Y;
float ZSquared = Z * Z;
float s = m.getColumn(0).length();
if ( s <= 0.00001 )
{
fprintf(stderr,"setHPR: bad matrix\n");
setValue(0,0,0);
return ;
}
s=1/s;
#define CLAMPTO1(x) x<-1 ? -1 : (x>1 ? 1 : x)
setY(asin(CLAMPTO1(m.getRow(2).getY())));
float cp = cos(getY());
/* If pointing nearly vertically up - then heading is ill-defined */
if ( cp > -0.00001 && cp < 0.00001 )
{
float cr = CLAMPTO1( m.getRow(1).getX()*s);
float sr = CLAMPTO1(-m.getRow(1).getZ()*s);
setX(0.0f);
setZ(atan2(sr, cr ));
}
else
{
cp = s / cp ; // includes the scaling factor
float sr = CLAMPTO1( -m.getRow(2).getX() * cp );
float cr = CLAMPTO1( m.getRow(2).getZ() * cp );
float sh = CLAMPTO1( -m.getRow(0).getY() * cp );
float ch = CLAMPTO1( m.getRow(1).getY() * cp );
if ( (sh == 0.0f && ch == 0.0f) || (sr == 0.0f && cr == 0.0f) )
{
cr = CLAMPTO1( m.getRow(1).getX()*s);
sr = CLAMPTO1(-m.getRow(1).getZ()*s) ;
setX(0.0f);
}
else
setX(atan2(sh, ch ));
setZ(atan2(sr, cr ));
}
} // setHPR
setX(atan2f(2.0f * (Y * Z + X * W), -XSquared - YSquared + ZSquared + WSquared));
setY(asinf(-2.0f * (X * Z - Y * W)));
setZ(atan2f(2.0f * (X * Y + Z * W), XSquared - YSquared - ZSquared + WSquared));
} // setHPR(btQuaternion)
// ----------------------------------------------------------------------------
void Vec3::degreeToRad()
@ -95,8 +58,8 @@ void Vec3::setPitchRoll(const Vec3 &normal)
// Compute the angle between the normal of the plane and the line to
// (x,y,0). (x,y,0) is normalised, so are the coordinates of the plane,
// simplifying the computation of the scalar product.
float pitch = ( normal.getX()*X + normal.getY()*Y ); // use ( x,y,0)
float roll = (-normal.getX()*Y + normal.getY()*X ); // use (-y,x,0)
float pitch = ( normal.getX()*X + normal.getZ()*Y ); // use ( x,y,0)
float roll = (-normal.getX()*Y + normal.getZ()*X ); // use (-y,x,0)
// The actual angle computed above is between the normal and the (x,y,0)
// line, so to compute the actual angles 90 degrees must be subtracted.
@ -111,22 +74,24 @@ void Vec3::setPitchRoll(const Vec3 &normal)
*/
const core::vector3df Vec3::toIrrHPR() const
{
core::vector3df r(RAD_TO_DEGREE*(-getY()), // pitch
RAD_TO_DEGREE*(-getX()), // heading
RAD_TO_DEGREE*(-getZ()) ); // roll
core::vector3df r(RAD_TO_DEGREE*(getX()), // pitch
RAD_TO_DEGREE*(getY()), // heading
RAD_TO_DEGREE*(getZ()) ); // roll
return r;
} // toIrrHPR
// ----------------------------------------------------------------------------
const core::vector3df Vec3::toIrrVector() const
/** Converts a vec3 into an irrlicht vector (which is a simple type cast).
*/
const core::vector3df& Vec3::toIrrVector() const
{
core::vector3df v(m_x, m_z, m_y);
return v;
return (const core::vector3df&)*this;
} // toIrrVector
// ----------------------------------------------------------------------------
/** Returns the X and Y component as an irrlicht 2d vector. */
const core::vector2df Vec3::toIrrVector2d() const
{
core::vector2df v(m_x, m_y);
core::vector2df v(m_x, m_z);
return v;
} // toIrrVector2d

View File

@ -40,8 +40,7 @@ public:
* axis as well (so a vector3df can be stored in and restored from
* a vec3).
*/
inline Vec3(const core::vector3df &v) : btVector3(v.X, v.Z, v.Y) {}
//inline Vec3(sgVec3 a) : btVector3(a[0], a[1], a[2]) {}
inline Vec3(const core::vector3df &v) : btVector3(v.X, v.Y, v.Z) {}
inline Vec3(const btVector3& a) : btVector3(a) {}
inline Vec3() : btVector3() {}
inline Vec3(float x, float y, float z) : btVector3(x,y,z) {}
@ -54,29 +53,28 @@ public:
{m_x=heading;
setPitchRoll(normal);}
void setHPR(const btMatrix3x3& m);
inline const float operator[](int n) const {return *(&m_x+n); }
inline const float getHeading() const {return m_x; }
inline const float getPitch() const {return m_y; }
inline const float getRoll() const {return m_z; }
inline const void setHeading(float f) {m_x = f;}
inline const void setPitch(float f) {m_y = f;}
inline const void setRoll(float f) {m_z = f;}
float* toFloat() const {return (float*)this; }
void setHPR(const btQuaternion& q);
inline const float operator[](int n) const { return *(&m_x+n); }
inline const float getHeading() const { return m_y; }
inline const float getPitch() const { return m_x; }
inline const float getRoll() const { return m_z; }
inline const void setHeading(float f) { m_y = f; }
inline const void setPitch(float f) { m_x = f; }
inline const void setRoll(float f) { m_z = f; }
/** Converts a Vec3 to an irrlicht 3d floating point vector. */
const core::vector3df toIrrVector() const;
const core::vector3df toIrrHPR() const;
const core::vector2df toIrrVector2d() const;
void degreeToRad();
const core::vector3df& toIrrVector() const;
const core::vector3df toIrrHPR() const;
const core::vector2df toIrrVector2d() const;
void degreeToRad();
Vec3& operator=(const btVector3& a) {*(btVector3*)this=a; return *this;}
Vec3& operator=(const btMatrix3x3& m) {setHPR(m); return *this;}
Vec3& operator=(const btQuaternion& q){setHPR(q); return *this;}
Vec3 operator-(const Vec3& v1) const {return (Vec3)(*(btVector3*)this-(btVector3)v1);}
/** Helper functions to treat this vec3 as a 2d vector. This returns the
* square of the length of the first 2 dimensions. */
float length2_2d() const {return m_x*m_x + m_y*m_y;}
float length2_2d() const {return m_x*m_x + m_z*m_z;}
/** Returns the length of this vector in the plane, i.e. the vector is
* used as a 2d vector. */
float length_2d() const {return sqrt(m_x*m_x + m_y*m_y);}
float length_2d() const {return sqrt(m_x*m_x + m_z*m_z);}
/** Sets this = max(this, a) componentwise.
* \param Vector to compare with. */
void max(const Vec3& a) {if(a.getX()>m_x) m_x=a.getX();