Merge remote-tracking branch 'origin/master' into Flakebi-fixes

This commit is contained in:
hiker 2015-07-20 09:10:05 +10:00
commit cd8fd7fb16
38 changed files with 616 additions and 384 deletions

View File

@ -154,15 +154,6 @@
otherwise obstricts too much of the view. -->
<camera distance="1.0" forward-up-angle="15"
backward-up-angle="5"/>
<!-- Options to affect the graphical chassis:
y-offset: Additional offset to move graphical chassis with regards
to the physics, used to reduce frequencey of graphical
chassis in terrain.
prevent-chassis-in-terrain: a hard flag to prevent nearly all instances
of chassis in terrain. Can (atm) cause some stuttering. -->
<graphics y-offset="0.0"
prevent-chassis-in-terrain="true"
/>
<!-- Jump animation related values:
animation-time: only if the estimated time for a jump is larger
@ -386,20 +377,20 @@
<!-- Suspension related values. stiffness: kart's suspension stiffness.
rest: Length of suspension when at rest.
travel-cm: maximum movement of suspension - in cm!!
travel: maximum movement of suspension!!
exp-string-response: dampen the suspension spring reaction
exponentially.
max-force: Maximum suspension force -->
<suspension stiffness="140" rest="0.3" travel-cm="29"
<suspension stiffness="140" rest="0.3" travel="0.29"
exp-spring-response="false" max-force="12000"/>
<!-- Wheel related parameters: damping-relaxation/compression: for
bullet, damping parameters. Radius and width of wheel.
bullet, damping parameters.
front-right, front-left, rear-right and rear-left give the
position of the physics raycast wheels relative to the center of
gravity. Default is to use the corners of the chassis to attach
the wheels to. -->
<wheels damping-relaxation="35" damping-compression="5" radius="0.25">
<wheels damping-relaxation="35" damping-compression="5">
<front-right position="0.38 0 0.6" />
<front-left position="-0.38 0 0.6" />
<rear-right position="0.38 0 -0.6" />

View File

@ -77,7 +77,7 @@ btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, con
ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
ci.m_frictionSlip = tuning.m_frictionSlip;
ci.m_bIsFrontWheel = isFrontWheel;
ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
ci.m_maxSuspensionTravel = tuning.m_maxSuspensionTravel;
ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
m_wheelInfo.push_back( btWheelInfo(ci));
@ -118,7 +118,7 @@ void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedT
btQuaternion steeringOrn(up,steering);//wheel.m_steering);
btMatrix3x3 steeringMat(steeringOrn);
btQuaternion rotatingOrn(right,-wheel.m_rotation);
btQuaternion rotatingOrn(right,0);
btMatrix3x3 rotatingMat(rotatingOrn);
btMatrix3x3 basis2(
@ -203,8 +203,8 @@ btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
//clamp on max suspension travel
btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01);
btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravel;
btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravel;
if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
{
wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
@ -345,17 +345,7 @@ void btRaycastVehicle::updateVehicle( btScalar step )
fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
btScalar proj2 = fwd.dot(vel);
wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
wheel.m_rotation += wheel.m_deltaRotation;
} else
{
wheel.m_rotation += wheel.m_deltaRotation;
}
wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact
}
}

View File

@ -43,7 +43,7 @@ public:
:m_suspensionStiffness(btScalar(5.88)),
m_suspensionCompression(btScalar(0.83)),
m_suspensionDamping(btScalar(0.88)),
m_maxSuspensionTravelCm(btScalar(500.)),
m_maxSuspensionTravel(btScalar(5.)),
m_frictionSlip(btScalar(10.5)),
m_maxSuspensionForce(btScalar(6000.))
{
@ -51,7 +51,7 @@ public:
btScalar m_suspensionStiffness;
btScalar m_suspensionCompression;
btScalar m_suspensionDamping;
btScalar m_maxSuspensionTravelCm;
btScalar m_maxSuspensionTravel;
btScalar m_frictionSlip;
btScalar m_maxSuspensionForce;

View File

@ -22,7 +22,7 @@ struct btWheelInfoConstructionInfo
btVector3 m_wheelDirectionCS;
btVector3 m_wheelAxleCS;
btScalar m_suspensionRestLength;
btScalar m_maxSuspensionTravelCm;
btScalar m_maxSuspensionTravel;
btScalar m_wheelRadius;
btScalar m_suspensionStiffness;
@ -59,7 +59,7 @@ struct btWheelInfo
btVector3 m_wheelDirectionCS;//const
btVector3 m_wheelAxleCS; // const or modified by steering
btScalar m_suspensionRestLength1;//const
btScalar m_maxSuspensionTravelCm;
btScalar m_maxSuspensionTravel;
btScalar getSuspensionRestLength() const;
btScalar m_wheelsRadius;//const
btScalar m_suspensionStiffness;//const
@ -67,8 +67,6 @@ struct btWheelInfo
btScalar m_wheelsDampingRelaxation;//const
btScalar m_frictionSlip;
btScalar m_steering;
btScalar m_rotation;
btScalar m_deltaRotation;
btScalar m_rollInfluence;
btScalar m_maxSuspensionForce;
@ -87,7 +85,7 @@ struct btWheelInfo
{
m_suspensionRestLength1 = ci.m_suspensionRestLength;
m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm;
m_maxSuspensionTravel = ci.m_maxSuspensionTravel;
m_wheelsRadius = ci.m_wheelRadius;
m_suspensionStiffness = ci.m_suspensionStiffness;
@ -99,8 +97,6 @@ struct btWheelInfo
m_frictionSlip = ci.m_frictionSlip;
m_steering = btScalar(0.);
m_engineForce = btScalar(0.);
m_rotation = btScalar(0.);
m_deltaRotation = btScalar(0.);
m_brake = btScalar(0.);
m_rollInfluence = btScalar(0.1);
m_bIsFrontWheel = ci.m_bIsFrontWheel;

View File

@ -1,5 +1,5 @@
# Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@ -257,7 +257,8 @@ void SFXManager::queueCommand(SFXCommand *command)
race_manager->getMinorMode() != RaceManager::MINOR_MODE_CUTSCENE)
{
if(command->m_command==SFX_POSITION || command->m_command==SFX_LOOP ||
command->m_command==SFX_SPEED )
command->m_command==SFX_SPEED ||
command->m_command==SFX_SPEED_POSITION )
{
delete command;
static int count_messages = 0;

View File

@ -463,7 +463,7 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
{
*above_kart = 0;
*cam_angle = 0;
*distance = -m_kart->getKartModel()->getLength();
*distance = -m_kart->getKartModel()->getLength()-1.0f;
}
else if(UserConfigParams::m_camera_debug==4)
{

View File

@ -18,23 +18,28 @@
#include "graphics/shadow.hpp"
#include "graphics/irr_driver.hpp"
#include "karts/kart_properties.hpp"
#include <IMesh.h>
#include <IMeshSceneNode.h>
#include <ISceneNode.h>
Shadow::Shadow(video::ITexture *texture, scene::ISceneNode *node,
float scale = 1.0, float x_offset = 0.0, float y_offset = 0.0,
float z_offset = 0.0)
Shadow::Shadow(const KartProperties *kart_properties,
scene::ISceneNode *node,
float y_offset = 0.0)
{
m_shadow_enabled = false;
video::SMaterial m;
m.setTexture(0, texture);
m.setTexture(0, kart_properties->getShadowTexture());
m.BackfaceCulling = false;
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m.setFlag(video::EMF_ZWRITE_ENABLE , false);
m_mesh = irr_driver->createQuadMesh(&m, /*create_one_quad*/true);
scene::IMeshBuffer *buffer = m_mesh->getMeshBuffer(0);
irr::video::S3DVertex* v=(video::S3DVertex*)buffer->getVertices();
float scale = kart_properties->getShadowScale();
float x_offset = kart_properties->getShadowXOffset();
float z_offset = kart_properties->getShadowXOffset();
v[0].Pos.X = -scale+x_offset; v[0].Pos.Z = scale+z_offset; v[0].Pos.Y = 0.01f-y_offset;
v[1].Pos.X = scale+x_offset; v[1].Pos.Z = scale+z_offset; v[1].Pos.Y = 0.01f-y_offset;
v[2].Pos.X = scale+x_offset; v[2].Pos.Z = -scale+z_offset; v[2].Pos.Y = 0.01f-y_offset;
@ -70,18 +75,17 @@ Shadow::~Shadow()
} // ~Shadow
// ----------------------------------------------------------------------------
/** Removes the shadow, used for the simplified shadow when the kart is in
* the air.
/** Updates the simulated shadow. It takes the offset (distance from visual
* chassis to ground) to position the shadow quad exactly on the ground.
* It also disables the shadow if requested (e.g. if the kart is in the air).
* \param enabled If the shadow should be shown or not.
* \param offset Distance from visual chassis to ground = position of the
* shadow to make sure it is exactly on the ground.
*/
void Shadow::disableShadow()
void Shadow::update(bool enabled, float offset)
{
m_node->setVisible(false);
}
// ----------------------------------------------------------------------------
/** Enables the shadow again, after it was disabled with disableShadow().
*/
void Shadow::enableShadow()
{
m_node->setVisible(true);
}
// ----------------------------------------------------------------------------
m_node->setVisible(enabled);
core::vector3df pos = m_node->getPosition();
pos.Y = offset;
m_node->setPosition(pos);
} // update

View File

@ -21,7 +21,7 @@
#include "utils/no_copy.hpp"
#include <string>
class KartProperties;
namespace irr
{
@ -41,19 +41,24 @@ class Shadow : public NoCopy
private:
/** The scene node for the shadow. */
scene::ISceneNode *m_node;
/** The mesh of the shadow. */
scene::IMesh *m_mesh;
/** The scene node of the kart to which this shadow belongs. */
scene::ISceneNode *m_parent_kart_node;
/** If a kart is flying, the shadow is disabled (since it is
* stuck to the kart, i.e. the shadow would be flying, too). */
bool m_shadow_enabled;
public:
Shadow(video::ITexture *texture, scene::ISceneNode *node,
float scale, float x_offset, float y_offset,float z_offset);
Shadow(const KartProperties *kart_properties,
scene::ISceneNode *node, float y_offset);
~Shadow();
void enableShadow();
void disableShadow();
void update(bool enabled, float hot);
}; // Shadow
#endif
/* EOF */

View File

@ -374,7 +374,7 @@ void Item::collected(const AbstractKart *kart, float t)
if (m_listener != NULL)
{
m_listener->onTriggerItemApproached(this);
m_listener->onTriggerItemApproached();
}
if (dynamic_cast<ThreeStrikesBattle*>(World::getWorld()) != NULL)

View File

@ -51,7 +51,7 @@ class TriggerItemListener
{
public:
virtual ~TriggerItemListener() {}
virtual void onTriggerItemApproached(Item* who) = 0;
virtual void onTriggerItemApproached() = 0;
};
/**

View File

@ -115,7 +115,6 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_bubblegum_torque = 0.0f;
m_invulnerable_time = 0.0f;
m_squash_time = 0.0f;
m_shadow_enabled = false;
m_shadow = NULL;
m_wheel_box = NULL;
@ -142,8 +141,6 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
// Set position and heading:
m_reset_transform = init_transform;
m_speed = 0.0f;
m_wheel_rotation = 0;
m_wheel_rotation_dt = 0;
m_kart_model->setKart(this);
@ -347,7 +344,6 @@ void Kart::reset()
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
m_collected_energy = 0;
m_has_started = false;
m_wheel_rotation = 0;
m_bounce_back_time = 0.0f;
m_brake_time = 0.0f;
m_time_last_crash = 0.0f;
@ -385,22 +381,6 @@ void Kart::reset()
{
m_vehicle->reset();
}
// Randomize wheel rotation if needed
if (m_kart_properties->hasRandomWheels() && m_vehicle && m_kart_model)
{
scene::ISceneNode** graphic_wheels = m_kart_model->getWheelNodes();
// FIXME Hardcoded i < 4 comes from the arrays in KartModel
for (int i = 0; i < m_vehicle->getNumWheels() && i < 4; i++)
{
// Physics
btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
wheel.m_rotation = btScalar(rand() % 360);
// And graphics
core::vector3df wheel_rotation(wheel.m_rotation, 0, 0);
if (graphic_wheels[i])
graphic_wheels[i]->setRotation(wheel_rotation);
} // for wheels
} // if random wheel rotation
setTrans(m_reset_transform);
@ -618,17 +598,12 @@ void Kart::createPhysics()
// All wheel positions are relative to the center of
// the collision shape.
wheel_pos[index].setX(x*0.5f*kart_width);
float radius = getKartProperties()->getWheelRadius();
// The y position of the wheels (i.e. the points where
// the suspension is attached to) is just at the
// bottom of the kart. That is half the kart height
// down. The wheel radius is added to the suspension
// length in the physics, so we move the connection
// point 'radius' up. That means that if the suspension
// is fully compressed (0), the wheel will just be at
// the bottom of the kart chassis and touch the ground
wheel_pos[index].setY(- 0.5f*kart_height + radius);
wheel_pos[index].setZ((0.5f*kart_length - radius)* z);
// down.
wheel_pos[index].setY(- 0.5f*kart_height);
wheel_pos[index].setZ((0.5f*kart_length-0.25f)* z);
}
else
@ -683,15 +658,14 @@ void Kart::createPhysics()
// Add wheels
// ----------
float wheel_radius = m_kart_properties->getWheelRadius();
float suspension_rest = m_kart_properties->getSuspensionRest();
btVector3 wheel_direction(0.0f, -1.0f, 0.0f);
btVector3 wheel_axle(-1.0f, 0.0f, 0.0f);
btKart::btVehicleTuning tuning;
tuning.m_maxSuspensionTravelCm =
m_kart_properties->getSuspensionTravelCM();
tuning.m_maxSuspensionTravel =
m_kart_properties->getSuspensionTravel();
tuning.m_maxSuspensionForce =
m_kart_properties->getMaxSuspensionForce();
@ -702,7 +676,8 @@ void Kart::createPhysics()
btWheelInfo& wheel = m_vehicle->addWheel(
wheel_pos[i]+cs,
wheel_direction, wheel_axle, suspension_rest,
wheel_radius, tuning, is_front_wheel);
m_kart_model->getWheelGraphicsRadius(i),
tuning, is_front_wheel);
wheel.m_suspensionStiffness = m_kart_properties->getSuspensionStiffness();
wheel.m_wheelsDampingRelaxation = m_kart_properties->getWheelDampingRelaxation();
wheel.m_wheelsDampingCompression = m_kart_properties->getWheelDampingCompression();
@ -1180,11 +1155,6 @@ void Kart::update(float dt)
m_kart_properties->getChassisAngularDamping());
}
//m_wheel_rotation gives the rotation around the X-axis
m_wheel_rotation_dt = m_speed*dt / m_kart_properties->getWheelRadius();
m_wheel_rotation += m_wheel_rotation_dt;
m_wheel_rotation = fmodf(m_wheel_rotation, 2*M_PI);
if(m_kart_animation)
m_kart_animation->update(dt);
@ -1393,21 +1363,6 @@ void Kart::update(float dt)
}
}
//const bool dyn_shadows = World::getWorld()->getTrack()->hasShadows() &&
// UserConfigParams::m_shadows &&
// irr_driver->isGLSL();
// Disable the fake shadow if we're flying
if(m_shadow && (!isOnGround() || emergency) && m_shadow_enabled)
{
m_shadow_enabled = false;
m_shadow->disableShadow();
}
if(m_shadow && !m_shadow_enabled && isOnGround() && !emergency)
{
m_shadow->enableShadow();
m_shadow_enabled = true;
}
} // update
//-----------------------------------------------------------------------------
@ -2132,11 +2087,11 @@ void Kart::updatePhysics(float dt)
// Only apply if near ground instead of purely based on speed avoiding
// the "parachute on top" look.
const Vec3 &v = m_body->getLinearVelocity();
if(/*isNearGround() &&*/ v.getY() < - m_kart_properties->getSuspensionTravelCM()*0.01f*60)
if(/*isNearGround() &&*/ v.getY() < - m_kart_properties->getSuspensionTravel()*60)
{
Vec3 v_clamped = v;
// clamp the speed to 99% of the maxium falling speed.
v_clamped.setY(-m_kart_properties->getSuspensionTravelCM()*0.01f*60 * 0.99f);
v_clamped.setY(-m_kart_properties->getSuspensionTravel()*60 * 0.99f);
//m_body->setLinearVelocity(v_clamped);
}
@ -2453,12 +2408,8 @@ void Kart::loadData(RaceManager::KartType type, bool is_animated_model)
if (!CVS->supportsShadows())
{
m_shadow = new Shadow(m_kart_properties->getShadowTexture(),
m_node,
m_kart_properties->getShadowScale(),
m_kart_properties->getShadowXOffset(),
m_kart_properties->getGraphicalYOffset(),
m_kart_properties->getShadowZOffset());
m_shadow = new Shadow(m_kart_properties, m_node,
-m_kart_model->getLowestPoint());
}
World::getWorld()->kartAdded(this, m_node);
} // loadData
@ -2492,11 +2443,12 @@ void Kart::applyEngineForce(float force)
//-----------------------------------------------------------------------------
/** Computes the transform of the graphical kart chasses with regards to the
* physical chassis. This function is called once the kart comes to rest
* before the race starts. Based on the current physical kart position, it
* computes an (at this stage Y-only) offset by which the graphical chassis
* is moved so that it appears the way it is designed in blender. This means
* that the distance of the wheels from the chassis (i.e. suspension) appears
* as in blender when karts are in rest.
* before the race starts (see World::resetAllKarts). Based on the current
* physical kart position it computes an (at this stage Y-only) offset by
* which the graphical chassis is moved so that it appears the way it is
* designed in blender. This means that the distance of the wheels from the
* chassis (i.e. suspension) appears as in blender when karts are in rest.
* See updateGraphics for more details.
*/
void Kart::kartIsInRestNow()
{
@ -2505,21 +2457,116 @@ void Kart::kartIsInRestNow()
for(int i=0; i<m_vehicle->getNumWheels(); i++)
{
const btWheelInfo &wi = m_vehicle->getWheelInfo(i);
f += wi.m_chassisConnectionPointCS.getY()
- wi.m_raycastInfo.m_suspensionLength - wi.m_wheelsRadius;
f += wi.m_raycastInfo.m_suspensionLength;
}
m_graphical_y_offset = f/m_vehicle->getNumWheels()
+ getKartProperties()->getGraphicalYOffset();
// The offset 'lowest point' is added to avoid that the
// visual chassis appears in the ground (it could be any
// constant, there is no real reason to use the lowest point
// but that value has worked good in the past). See documentation
// for updateGraphics() for full details.
m_graphical_y_offset = -f / m_vehicle->getNumWheels()
+ m_kart_model->getLowestPoint();
m_kart_model->setDefaultSuspension();
} // kartIsInRestNow
//-----------------------------------------------------------------------------
/** 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.
/** Updates the graphics model. It is responsible for positioning the graphical
* chasses at an 'appropriate' position: typically, the physical model has
* much longer suspension, so if the graphical chassis would be at the same
* location as the physical chassis, the wheels would be too far away.
* Instead the default suspension length is saved once the kart have been
* settled at start up (see World::resetAllKarts, which just runs several
* physics-only simulation steps so that karts come to a rest). Then at
* race time, only the difference between the current suspension length and
* this default suspension length is used. The graphical kart chassis will be
* offset so that when the kart is in rest, i.e. suspension length ==
* default suspension length, the kart will look the way it was modelled in
* blender. To explain the various offsets used, here a view from the side
* focusing on the Y axis only (X/Z position of the graphical chassis is
* identical to the physical chassis):
*
* Y| | visual kart | physical kart
* | | |
* | | |
* | | |
* | | +-------------COG---------------
* | | :
* | +---------low------ :
* | O :
* +--------------------------------------------------------------------------
* X
* 'O' : visual wheel ':' : raycast from physics
* 'low' : lowest Y coordinate of COG : Center of gravity (at bottom of
* model chassis)
*
* The visual kart is stored so that if it is shown at (0,0,0) it would be
* the same as in blender. This on the other hand means, if the kart is shown
* at the position of the physical chassis (which is at COG in the picture
* above), the kart and its wheels would be floating in the air (exactly by
* as much as the suspension length), and the wheels would be exactly at the
* bottom of the physical chassis (i.e. just on the plane going through COG
* and parallel to the ground).
* If we want to align the visual chassis to be the same as the physical
* chassis, we would need to subtract 'low' from the physical position.
* If the kart is then displayed at COG.y-low, the bottom of the kart (which
* is at 'low' above ground) would be at COG.y-low + low = COG.y --> visual
* and physical chassis are identical.
*
* Unfortunately, the suspension length used in the physics is much too high,
* the karts would be way above their wheels, basically disconneccted
* (typical physical suspension length is around 0.28, while the distance
* between wheel and chassis in blender is in the order of 0.10 --> so there
* would be an additional distance of around 0.18 between wheel chassis as
* designed in blender and in stk - even more if the kart is driving downhill
* when the suspension extends further to keep contact with the ground).
* To make the visuals look closer to what they are in blender, an additional
* offset is added: before the start of a race the physics simulation is run
* to find a stable position for each kart (see World::resetAllKarts). Once
* a kart is stable, we save this suspension length in m_graphical_y_offset.
* This offset is subtracted from the COG of the kart. So if the kart is in
* rest (i.e. suspenion == default_suspension == m_graphical_y_offset),
* The kart is showen exactly at the same height above ground as it is in
* blender. If the suspension is shorter by DY (because the kart is
* accelerating, the ground goes up, ...), the visual chassis is lowered by
* DY as well.
*
* While the above algorithm indeed results in the right position of the
* visual chassis, in reality the visual chassis is too low. For example,
* nolok's chassis has its lowest point at the rear at around 0.10 above the
* ground (and the lowest point overall is 0.05, though this is at the front
* and so not easily visible), so if the suspension is compressed by more than
* that, the chassiswill appear to be in the ground. Testing on the sand track
* shows that the suspension is compressed by 0.12 (and up to 0.16 in some
* extreme points), which means that the chassis will appear to be in the
* ground quite easily. Therefore the chassis is actually moved up a bit to
* avoid this problem. Historically (due to never sorting out that formula
* properly) the chassis was moved twice as high as its lowest point, e.g.
* nolok's lowest point is at 0.05, so the whole chassis was raised by 0.05
* (this was not done by design, but because of a bug ;) ). Since this visual
* offset has worked well in the past, the visual chassis is moved by the
* same amount higher.
*
* Of course this means that the Y position of the wheels (relative to the
* visual kart chassis) needs to be adjusted: if the kart is in rest, the
* wheels are exactly on the ground. If the suspension is shorter, that wheel
* would appear to be partly in the ground, and if the suspension is longer,
* the wheel would not touch the ground.
*
* The wheels must be offset by how much the current suspension length is
* longer or shorter than the default (i.e. at rest) suspension length.
* This is done in KartModel (pos is the position of the wheel relative
* to the visual kart chassis):
* pos.Y += m_default_physics_suspension[i]
* - wi.m_raycastInfo.m_suspensionLength
* But since the chassis is raised an additional 'getLowestPoint' (see
* desctiption two paragraphs above), the wheels need to be lowered by that
* amount so that they still touch the ground (the wheel nodes are child of
* the chassis scene node, so if the chassis is raised by X, the wheels need
* to be lowered by X).
* This function also takes additional graphical effects into account, e.g.
* a (visual only) jump when skidding, and leaning of the kart.
* \param offset_xyz Offset to be added to the position.
* \param rotation Additional rotation.
*/
@ -2601,60 +2648,37 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
}
}
m_kart_model->update(dt, m_wheel_rotation_dt, getSteerPercent(), m_speed);
// If the kart is leaning, part of the kart might end up 'in' the track.
// To avoid this, raise the kart enough to offset the leaning.
float lean_height = tan(fabsf(m_current_lean)) * getKartWidth()*0.5f;
float heading = m_skidding->getVisualSkidRotation();
float xx = fabsf(m_speed)* getKartProperties()->getDownwardImpulseFactor()*0.0006f;
Vec3 center_shift = Vec3(0, m_skidding->getGraphicalJumpOffset()
+ lean_height +m_graphical_y_offset+xx, 0);
// Try to prevent the graphical chassis to be inside of the terrain:
if(m_kart_properties->getPreventChassisInTerrain())
{
// Get the shortest suspension length (=closest point to terrain).
float min_susp_len = 99.9f;
for (int i = 0; i < getVehicle()->getNumWheels(); i++)
{
float susp_len = getVehicle()->getWheelInfo(i).m_raycastInfo
.m_suspensionLength;
if (susp_len < min_susp_len)
min_susp_len = susp_len;
} // for i<num_wheels
const btWheelInfo &w = getVehicle()->getWheelInfo(0);
// Recompute the default average suspension length, see
// kartIsInRestNow() how to get from y-offset to susp. len.
float av_sus_len = -m_graphical_y_offset
+ w.m_chassisConnectionPointCS.getY()
- w.m_wheelsRadius;
float delta = av_sus_len - min_susp_len;
// If the suspension length is so short, that it is less than the
// lowest point of the kart, it indicates that the graphical chassis
// would be inside of the track:
if (delta > m_kart_model->getLowestPoint())
{
center_shift.setY(center_shift.getY() + delta - m_kart_model->getLowestPoint());
}
// FIXME: for now, debug output in case we have to debug it
//Log::verbose("kart", "min %f y off %f overall off %f lowest %f delta %f asl %f",
// min_susp_len, m_graphical_y_offset, center_shift.getY(),
// m_kart_model->getLowestPoint(),
// delta,
// av_sus_len
// );
}
Vec3 center_shift(0, 0, 0);
center_shift.setY(m_skidding->getGraphicalJumpOffset()
+ lean_height
+m_graphical_y_offset);
center_shift = getTrans().getBasis() * center_shift;
float heading = m_skidding->getVisualSkidRotation();
Moveable::updateGraphics(dt, center_shift,
btQuaternion(heading, 0, m_current_lean));
// m_speed*dt is the distance the kart has moved, which determines
// how much the wheels need to rotate.
m_kart_model->update(dt, m_speed*dt, getSteerPercent(), m_speed);
// Determine the shadow position from the terrain Y position. This
// leaves the shadow on the ground even if the kart is jumping because
// of skidding (shadows are disabled when wheel are not on the track).
if (m_shadow)
{
const bool emergency = getKartAnimation() != NULL;
m_shadow->update(isOnGround() && !emergency,
m_terrain_info->getHoT() - getXYZ().getY()
- m_skidding->getGraphicalJumpOffset()
- m_graphical_y_offset
- m_kart_model->getLowestPoint());
}
#ifdef XX
// cheap wheelie effect
if (m_controls.m_nitro)

View File

@ -173,10 +173,6 @@ private:
/** The shadow of a kart. */
Shadow *m_shadow;
/** If a kart is flying, the shadow is disabled (since it is
* stuck to the kart, i.e. the shadow would be flying, too). */
bool m_shadow_enabled;
ParticleEmitter *m_sky_particles_emitter;
/** All particle effects. */
@ -188,12 +184,6 @@ private:
/** Handles all slipstreaming. */
SlipStream *m_slipstream;
/** Rotation compared to the start position, same for all wheels */
float m_wheel_rotation;
/** Rotation change in the last time delta, same for all wheels */
float m_wheel_rotation_dt;
/** The skidmarks object for this kart. */
SkidMarks *m_skidmarks;

View File

@ -49,30 +49,38 @@ float KartModel::UNDEFINED = -99.9f;
SpeedWeightedObject::Properties::Properties()
{
m_strength_factor = m_speed_factor = m_texture_speed.X = m_texture_speed.Y = SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED;
}
m_strength_factor = SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED;
m_speed_factor = SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED;
m_texture_speed.X = SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED;
m_texture_speed.Y = SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED;
} // SpeedWeightedObject::Properties::Properties
// ----------------------------------------------------------------------------
void SpeedWeightedObject::Properties::loadFromXMLNode(const XMLNode* xml_node)
{
xml_node->get("strength-factor", &m_strength_factor);
xml_node->get("speed-factor", &m_speed_factor);
xml_node->get("texture-speed-x", &m_texture_speed.X);
xml_node->get("texture-speed-y", &m_texture_speed.Y);
}
} // SpeedWeightedObject::Properties::loadFromXMLNode
// ----------------------------------------------------------------------------
void SpeedWeightedObject::Properties::checkAllSet()
{
#define CHECK_NEG( a,strA) if(a<=SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED) { \
Log::fatal("SpeedWeightedObject", "Missing default value for '%s'.", \
strA); \
#define CHECK_NEG( a,strA) if(a<=SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED) \
{ \
Log::fatal("SpeedWeightedObject", \
"Missing default value for '%s'.", \
strA); \
}
CHECK_NEG(m_strength_factor, "speed-weighted strength-factor" );
CHECK_NEG(m_speed_factor, "speed-weighted speed-factor" );
CHECK_NEG(m_strength_factor, "speed-weighted strength-factor" );
CHECK_NEG(m_speed_factor, "speed-weighted speed-factor" );
CHECK_NEG(m_texture_speed.X, "speed-weighted texture speed X" );
CHECK_NEG(m_texture_speed.Y, "speed-weighted texture speed Y" );
#undef CHECK_NEG
}
} // SpeedWeightedObject::Properties::checkAllSet
// ============================================================================
/** Default constructor which initialises all variables with defaults.
* Note that the KartModel is copied, so make sure to update makeCopy
* if any more variables are added to this object.
@ -158,8 +166,8 @@ void KartModel::loadInfo(const XMLNode &node)
animation_node->get("start-jump", &m_animation_frame[AF_JUMP_START]);
animation_node->get("start-jump-loop",&m_animation_frame[AF_JUMP_LOOP] );
animation_node->get("end-jump", &m_animation_frame[AF_JUMP_END] );
animation_node->get("start-speed-weighted", &m_animation_frame[AF_SPEED_WEIGHTED_START] );
animation_node->get("end-speed-weighted", &m_animation_frame[AF_SPEED_WEIGHTED_END] );
animation_node->get("start-speed-weighted", &m_animation_frame[AF_SPEED_WEIGHTED_START]);
animation_node->get("end-speed-weighted", &m_animation_frame[AF_SPEED_WEIGHTED_END] );
animation_node->get("speed", &m_animation_speed );
}
@ -451,10 +459,12 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
obj.m_node = NULL;
if(obj.m_model)
{
obj.m_node = irr_driver->addAnimatedMesh(obj.m_model, "speedweighted", node);
obj.m_node = irr_driver->addAnimatedMesh(obj.m_model,
"speedweighted", node);
obj.m_node->grab();
obj.m_node->setFrameLoop(m_animation_frame[AF_SPEED_WEIGHTED_START], m_animation_frame[AF_SPEED_WEIGHTED_END]);
obj.m_node->setFrameLoop(m_animation_frame[AF_SPEED_WEIGHTED_START],
m_animation_frame[AF_SPEED_WEIGHTED_END]);
#ifdef DEBUG
std::string debug_name = obj.m_name+" (speed-weighted)";
@ -553,14 +563,6 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
}
}
float y_off = kart_properties.getGraphicalYOffset();
if(y_off!=0)
{
for (unsigned int i = 0; i < 4; i++)
m_wheel_graphics_position[i].setY(
m_wheel_graphics_position[i].getY() - y_off);
}
// Load the wheel models. This can't be done early, since the default
// values for the graphical position must be defined, which in turn
// depend on the size of the model.
@ -644,6 +646,14 @@ void KartModel::loadWheelInfo(const XMLNode &node,
*/
void KartModel::reset()
{
for (unsigned int i = 0; i < 4; i++)
{
if (m_wheel_node[i])
{
core::vector3df rotation(btScalar(rand() % 360), 0, 0);
m_wheel_node[i]->setRotation(rotation);
}
}
update(0.0f, 0.0f, 0.0f, 0.0f);
// Stop any animations currently being played.
@ -766,49 +776,44 @@ void KartModel::setDefaultSuspension()
// ----------------------------------------------------------------------------
/** Rotates and turns the wheels appropriately, and adjust for suspension
+ updates the speed-weighted objects' animations.
* updates the speed-weighted objects' animations.
*
* \param dt time since last frame
* \param rotation_dt How far the wheels have rotated since last time.
* \param distance How far the wheels have rotated since last time.
* \param steer The actual steer settings.
* \param suspension Suspension height for all four wheels.
* \param speed The speed of the kart in meters/sec, used for the
* speed-weighted objects' animations
*/
void KartModel::update(float dt, float rotation_dt, float steer, float speed)
void KartModel::update(float dt, float distance, float steer, float speed)
{
core::vector3df wheel_steer(0, steer*30.0f, 0);
core::vector3df wheel_steer(0, steer*30.0f, 0);
for(unsigned int i=0; i<4; i++)
{
if(!m_kart || !m_wheel_node[i]) continue;
float rel_suspension = 0;
if (!dynamic_cast<GhostKart*>(m_kart))
{
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
if (!m_kart || !m_wheel_node[i]) continue;
#ifdef DEBUG
if (UserConfigParams::m_physics_debug && m_kart)
{
// Make wheels that are not touching the ground invisible
m_wheel_node[i]->setVisible(wi.m_raycastInfo.m_isInContact);
}
if (UserConfigParams::m_physics_debug &&
!dynamic_cast<GhostKart*>(m_kart) )
{
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
// Make wheels that are not touching the ground invisible
m_wheel_node[i]->setVisible(wi.m_raycastInfo.m_isInContact);
}
#endif
rel_suspension = wi.m_raycastInfo.m_suspensionLength
- m_default_physics_suspension[i];
}
// If the suspension is too compressed
if(rel_suspension< m_min_suspension[i])
rel_suspension = m_min_suspension[i];
else if(rel_suspension > m_max_suspension[i])
rel_suspension = m_max_suspension[i];
core::vector3df pos = m_wheel_graphics_position[i].toIrrVector();
pos.Y -= rel_suspension;
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
// Check documentation of Kart::updateGraphics for the following line
pos.Y += m_default_physics_suspension[i]
- wi.m_raycastInfo.m_suspensionLength
- m_kart_lowest_point;
m_wheel_node[i]->setPosition(pos);
// Now calculate the new rotation: (old + change) mod 360
float new_rotation = m_wheel_node[i]->getRotation().X
+ rotation_dt * RAD_TO_DEGREE;
+ distance / m_wheel_graphics_radius[i] * RAD_TO_DEGREE;
new_rotation = fmodf(new_rotation, 360);
core::vector3df wheel_rotation(new_rotation, 0, 0);
// Only apply steer to first 2 wheels.

View File

@ -232,7 +232,7 @@ public:
void loadInfo(const XMLNode &node);
bool loadModels(const KartProperties &kart_properties);
void setDefaultSuspension();
void update(float dt, float rotation_dt, float steer,
void update(float dt, float distance, float steer,
float speed);
void finishedRace();
scene::ISceneNode*

View File

@ -70,11 +70,11 @@ KartProperties::KartProperties(const std::string &filename)
m_nitro_max_speed_increase = m_nitro_duration = m_nitro_fade_out_time =
m_suspension_stiffness = m_wheel_damping_relaxation = m_wheel_base =
m_wheel_damping_compression = m_friction_slip = m_roll_influence =
m_wheel_radius = m_chassis_linear_damping = m_max_suspension_force =
m_chassis_linear_damping = m_max_suspension_force =
m_chassis_angular_damping = m_suspension_rest =
m_max_speed_reverse_ratio = m_rescue_vert_offset =
m_collision_terrain_impulse = m_collision_impulse = m_restitution =
m_collision_impulse_time = m_suspension_travel_cm =
m_collision_impulse_time = m_suspension_travel =
m_track_connection_accel = m_rubber_band_max_length =
m_rubber_band_force = m_rubber_band_duration =
m_rubber_band_speed_increase = m_rubber_band_fade_out_time =
@ -93,7 +93,6 @@ KartProperties::KartProperties(const std::string &filename)
m_bubblegum_fade_in_time = m_bubblegum_speed_fraction =
m_bubblegum_time = m_bubblegum_torque = m_jump_animation_time =
m_smooth_flying_impulse = m_physical_wheel_position =
m_graphical_y_offset =
UNDEFINED;
m_engine_power.resize(RaceManager::DIFFICULTY_COUNT, UNDEFINED);
@ -105,13 +104,11 @@ KartProperties::KartProperties(const std::string &filename)
m_gravity_center_shift = Vec3(UNDEFINED);
m_bevel_factor = Vec3(UNDEFINED);
m_exp_spring_response = false;
m_prevent_chassis_in_terrain = false;
m_version = 0;
m_color = video::SColor(255, 0, 0, 0);
m_shape = 32; // close enough to a circle.
m_engine_sfx_type = "engine_small";
m_kart_model = NULL;
m_has_rand_wheels = false;
m_nitro_min_consumption = 0.53f;
// The default constructor for stk_config uses filename=""
if (filename != "")
@ -281,7 +278,13 @@ void KartProperties::load(const std::string &filename, const std::string &node)
{
m_gravity_center_shift.setX(0);
// Default: center at the very bottom of the kart.
m_gravity_center_shift.setY(m_kart_model->getHeight()*0.5f);
// If the kart is 'too high', its height will be changed in
// kart.cpp, the same adjustment needs to be made here.
if (m_kart_model->getHeight() > m_kart_model->getLength()*0.6f)
m_gravity_center_shift.setY(m_kart_model->getLength()*0.6f*0.5f);
else
m_gravity_center_shift.setY(m_kart_model->getHeight()*0.5f);
m_gravity_center_shift.setZ(0);
}
@ -292,7 +295,10 @@ void KartProperties::load(const std::string &filename, const std::string &node)
// moved to be on the corner of the shape. In order to retain the same
// steering behaviour, the wheel base (which in turn determines the
// turn angle at certain speeds) is shortened by 2*wheel_radius
m_wheel_base = fabsf(m_kart_model->getLength() - 2*m_wheel_radius);
// Wheel radius was always 0.25, and is now not used anymore, but in order
// to keep existing steering behaviour, the same formula is still
// used.
m_wheel_base = fabsf(m_kart_model->getLength() - 2*0.25f);
// Now convert the turn radius into turn angle:
for(unsigned int i=0; i<m_turn_angle_at_speed.size(); i++)
@ -330,8 +336,6 @@ void KartProperties::getAllData(const XMLNode * root)
root->get("groups", &m_groups );
root->get("random-wheel-rot", &m_has_rand_wheels );
root->get("shadow-scale", &m_shadow_scale );
root->get("shadow-x-offset", &m_shadow_x_offset );
root->get("shadow-z-offset", &m_shadow_z_offset );
@ -357,7 +361,7 @@ void KartProperties::getAllData(const XMLNode * root)
{
suspension_node->get("stiffness", &m_suspension_stiffness);
suspension_node->get("rest", &m_suspension_rest );
suspension_node->get("travel-cm", &m_suspension_travel_cm);
suspension_node->get("travel", &m_suspension_travel );
suspension_node->get("exp-spring-response", &m_exp_spring_response );
suspension_node->get("max-force", &m_max_suspension_force);
}
@ -366,7 +370,6 @@ void KartProperties::getAllData(const XMLNode * root)
{
wheels_node->get("damping-relaxation", &m_wheel_damping_relaxation );
wheels_node->get("damping-compression", &m_wheel_damping_compression);
wheels_node->get("radius", &m_wheel_radius );
}
if(const XMLNode *speed_weighted_objects_node = root->getNode("speed-weighted-objects"))
@ -627,13 +630,6 @@ void KartProperties::getAllData(const XMLNode * root)
startup_node->get("boost", &m_startup_boost);
}
if(const XMLNode *graphics_node = root->getNode("graphics"))
{
graphics_node->get("y-offset", &m_graphical_y_offset);
graphics_node->get("prevent-chassis-in-terrain",
&m_prevent_chassis_in_terrain);
}
if(m_kart_model)
m_kart_model->loadInfo(*root);
} // getAllData
@ -681,7 +677,6 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_time_reset_steer, "turn time-reset-steer" );
CHECK_NEG(m_wheel_damping_relaxation, "wheels damping-relaxation" );
CHECK_NEG(m_wheel_damping_compression, "wheels damping-compression" );
CHECK_NEG(m_wheel_radius, "wheels radius" );
CHECK_NEG(m_friction_slip, "friction slip" );
CHECK_NEG(m_roll_influence, "stability roll-influence" );
CHECK_NEG(m_chassis_linear_damping, "stability chassis-linear-damping" );
@ -694,7 +689,7 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_brake_time_increase, "engine brake-time-increase" );
CHECK_NEG(m_suspension_stiffness, "suspension stiffness" );
CHECK_NEG(m_suspension_rest, "suspension rest" );
CHECK_NEG(m_suspension_travel_cm, "suspension travel-cm" );
CHECK_NEG(m_suspension_travel, "suspension travel" );
CHECK_NEG(m_max_suspension_force, "suspension max-force" );
CHECK_NEG(m_collision_impulse, "collision impulse" );
CHECK_NEG(m_collision_impulse_time, "collision impulse-time" );
@ -754,7 +749,7 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_explosion_invulnerability_time,
"explosion invulnerability-time");
CHECK_NEG(m_explosion_radius, "explosion radius" );
CHECK_NEG(m_graphical_y_offset, "graphics y-offset" );
for(unsigned int i=RaceManager::DIFFICULTY_FIRST;
i<=RaceManager::DIFFICULTY_LAST; i++)
{

View File

@ -208,11 +208,6 @@ private:
* chassis. Useful for karts that don't have enough space for suspension
* compression. */
float m_graphical_y_offset;
/** A hard flag that moves the graphical chassis higher if it's insde
* the track. Might cause stuttering. */
bool m_prevent_chassis_in_terrain;
/** If the kart is supposed to have random wheel rotation at start. */
bool m_has_rand_wheels;
/** Max. length of plunger rubber band. */
float m_rubber_band_max_length;
/** Force of an attached rubber band. */
@ -288,7 +283,6 @@ private:
float m_max_suspension_force;
float m_friction_slip;
float m_roll_influence;
float m_wheel_radius;
/** Parameters for the speed-weighted objects */
SpeedWeightedObject::Properties m_speed_weighted_object_properties;
@ -324,7 +318,7 @@ private:
bool m_exp_spring_response;
float m_suspension_rest;
float m_suspension_travel_cm;
float m_suspension_travel;
public:
/** STK can add an impulse to push karts away from the track in case
@ -571,22 +565,6 @@ public:
/** Returns roll influence. */
float getRollInfluence () const {return m_roll_influence; }
// ------------------------------------------------------------------------
/** Returns wheel radius. */
float getWheelRadius () const {return m_wheel_radius; }
// ------------------------------------------------------------------------
/** Return the additional Y offset added to the y position of the graphical
* chassis. Useful for karts that don't have enough space for suspension
* compression. */
float getGraphicalYOffset() const {return m_graphical_y_offset; }
// ------------------------------------------------------------------------
/** A hard flag that moves the graphical chassis higher if it's insde
* the track. Might cause stuttering. */
bool getPreventChassisInTerrain() const
{
return m_prevent_chassis_in_terrain;
} // getPreventChassisInTerrain
// ------------------------------------------------------------------------
/** Returns parameters for the speed-weighted objects */
const SpeedWeightedObject::Properties& getSpeedWeightedObjectProperties() const
@ -685,7 +663,7 @@ public:
// ------------------------------------------------------------------------
/** Returns the amount the suspension can extend. */
float getSuspensionTravelCM () const {return m_suspension_travel_cm; }
float getSuspensionTravel () const {return m_suspension_travel; }
// ------------------------------------------------------------------------
/** Returns if the spring should be exponentially dampened. */
@ -926,9 +904,6 @@ public:
* animation. */
float getJumpAnimationTime() const { return m_jump_animation_time; }
// ------------------------------------------------------------------------
/** Returns true if wheels should have random rotation at start. */
bool hasRandomWheels() const { return m_has_rand_wheels; }
// ------------------------------------------------------------------------
/** Returns minimum time during which nitro is consumed when pressing nitro
* key, to prevent using nitro in very short bursts
*/

71
src/karts/patch Normal file
View File

@ -0,0 +1,71 @@
diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp
index de14bbe..47bbee9 100644
--- a/src/karts/kart.cpp
+++ b/src/karts/kart.cpp
@@ -2476,11 +2476,12 @@ void Kart::kartIsInRestNow()
for(int i=0; i<m_vehicle->getNumWheels(); i++)
{
const btWheelInfo &wi = m_vehicle->getWheelInfo(i);
- f += wi.m_chassisConnectionPointCS.getY()
- - wi.m_raycastInfo.m_suspensionLength - wi.m_wheelsRadius;
+ f += wi.m_raycastInfo.m_suspensionLength;
}
+ m_terrain_info->update(getTrans());
m_graphical_y_offset = f/m_vehicle->getNumWheels()
+ getKartProperties()->getGraphicalYOffset();
+ m_graphical_y_offset = m_kart_model->getLowestPoint() - (getXYZ().getY() - m_terrain_info->getHoT());
m_kart_model->setDefaultSuspension();
} // kartIsInRestNow
@@ -2595,11 +2596,6 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
} // for i<num_wheels
const btWheelInfo &w = getVehicle()->getWheelInfo(0);
- // Determine the shadow position from the terrain Y position. This
- // leaves the shadow on the ground even if the kart is jumping because
- // of skidding (shadows are disabled when wheel are not on the track).
- m_shadow->update(m_terrain_info->getHoT() - getXYZ().getY()
- -m_skidding->getGraphicalJumpOffset());
// Recompute the default average suspension length, see
// kartIsInRestNow() how to get from y-offset to susp. len.
float av_sus_len = -m_graphical_y_offset
@@ -2628,6 +2624,9 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
+ lean_height
- m_kart_model->getLowestPoint());
+ center_shift.setY(m_skidding->getGraphicalJumpOffset()
+ + lean_height
+ +m_graphical_y_offset);
center_shift = getTrans().getBasis() * center_shift;
Moveable::updateGraphics(dt, center_shift,
@@ -2637,6 +2636,14 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
// how much the wheels need to rotate.
m_kart_model->update(dt, m_speed*dt, getSteerPercent(), m_speed);
+ // Determine the shadow position from the terrain Y position. This
+ // leaves the shadow on the ground even if the kart is jumping because
+ // of skidding (shadows are disabled when wheel are not on the track).
+ m_shadow->update( m_terrain_info->getHoT() - getXYZ().getY()
+ - m_skidding->getGraphicalJumpOffset()
+ - m_graphical_y_offset
+ - m_kart_model->getLowestPoint());
+
#ifdef XX
// cheap wheelie effect
if (m_controls.m_nitro)
diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp
index 65879d3..36b03b7 100644
--- a/src/karts/kart_model.cpp
+++ b/src/karts/kart_model.cpp
@@ -813,7 +813,9 @@ void KartModel::update(float dt, float distance, float steer, float speed)
core::vector3df pos = m_wheel_graphics_position[i].toIrrVector();
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
- pos.Y = -wi.m_raycastInfo.m_suspensionLength + m_wheel_graphics_radius[i] + getLowestPoint();
+ pos.Y += m_default_physics_suspension[i]
+ - wi.m_raycastInfo.m_suspensionLength
+ - getLowestPoint();
m_wheel_node[i]->setPosition(pos);
// Now calculate the new rotation: (old + change) mod 360

View File

@ -173,7 +173,13 @@ public:
{
return m_kart_info[kart_index].m_track_sector;
} // getTrackSector
// ------------------------------------------------------------------------
void setLastTriggeredCheckline(unsigned int kart_index, int index)
{
if (m_kart_info.size() == 0)
return;
m_kart_info[kart_index].m_track_sector.setLastTriggeredCheckline(index);
}
// ------------------------------------------------------------------------
/** Returns how far the kart has driven so far (i.e.
* number-of-laps-finished times track-length plus distance-on-track.

View File

@ -128,6 +128,7 @@ void OverWorld::update(float dt)
m_karts[n]->setEnergy(100.0f);
}
/*
TrackObjectManager* tom = getTrack()->getTrackObjectManager();
PtrVector<TrackObject>& objects = tom->getObjects();
for(unsigned int i=0; i<objects.size(); i++)
@ -145,6 +146,7 @@ void OverWorld::update(float dt)
obj->reset();
}
}
*/
if (m_return_to_garage)
{

View File

@ -83,7 +83,7 @@ btWheelInfo& btKart::addWheel(const btVector3& connectionPointCS,
ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
ci.m_frictionSlip = tuning.m_frictionSlip;
ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
ci.m_maxSuspensionTravel = tuning.m_maxSuspensionTravel;
ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
m_wheelInfo.push_back( btWheelInfo(ci));
@ -112,7 +112,6 @@ void btKart::reset()
{
btWheelInfo &wheel = m_wheelInfo[i];
wheel.m_raycastInfo.m_suspensionLength = 0;
wheel.m_rotation = 0;
updateWheelTransform(i, true);
}
m_visual_wheels_touch_ground = false;
@ -159,16 +158,13 @@ void btKart::updateWheelTransform(int wheelIndex, bool interpolatedTransform)
btQuaternion steeringOrn(up,steering);//wheel.m_steering);
btMatrix3x3 steeringMat(steeringOrn);
btQuaternion rotatingOrn(right,-wheel.m_rotation);
btMatrix3x3 rotatingMat(rotatingOrn);
btMatrix3x3 basis2(
right[0],fwd[0],up[0],
right[1],fwd[1],up[1],
right[2],fwd[2],up[2]
);
wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
wheel.m_worldTransform.setBasis(steeringMat * basis2);
wheel.m_worldTransform.setOrigin(
wheel.m_raycastInfo.m_hardPointWS
+ wheel.m_raycastInfo.m_wheelDirectionWS
@ -235,8 +231,8 @@ btScalar btKart::rayCast(unsigned int index)
updateWheelTransformsWS( wheel,false);
btScalar max_susp_len = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius
+ wheel.m_maxSuspensionTravelCm*0.01f;
btScalar max_susp_len = wheel.getSuspensionRestLength()
+ wheel.m_maxSuspensionTravel;
// Do a slightly longer raycast to see if the kart might soon hit the
// ground and some 'cushioning' is needed to avoid that the chassis
@ -266,13 +262,13 @@ btScalar btKart::rayCast(unsigned int index)
wheel.m_raycastInfo.m_triangle_index = rayResults.m_triangle_index;;
wheel.m_raycastInfo.m_groundObject = &getFixedBody();
wheel.m_raycastInfo.m_suspensionLength = depth - wheel.m_wheelsRadius;
wheel.m_raycastInfo.m_suspensionLength = depth;
//clamp on max suspension travel
btScalar minSuspensionLength = wheel.getSuspensionRestLength()
- wheel.m_maxSuspensionTravelCm*btScalar(0.01);
- wheel.m_maxSuspensionTravel;
btScalar maxSuspensionLength = wheel.getSuspensionRestLength()
+ wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+ wheel.m_maxSuspensionTravel;
if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
{
wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
@ -524,15 +520,8 @@ void btKart::updateVehicle( btScalar step )
btScalar proj2 = fwd.dot(vel);
wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
wheel.m_rotation += wheel.m_deltaRotation;
} else
{
wheel.m_rotation += wheel.m_deltaRotation;
}
//damping of rotation when not in contact
wheel.m_deltaRotation *= btScalar(0.99);
}
}

View File

@ -37,7 +37,7 @@ public:
:m_suspensionStiffness(btScalar(5.88)),
m_suspensionCompression(btScalar(0.83)),
m_suspensionDamping(btScalar(0.88)),
m_maxSuspensionTravelCm(btScalar(500.)),
m_maxSuspensionTravel(btScalar(5.)),
m_frictionSlip(btScalar(10.5)),
m_maxSuspensionForce(btScalar(6000.))
{
@ -46,7 +46,7 @@ public:
btScalar m_suspensionStiffness;
btScalar m_suspensionCompression;
btScalar m_suspensionDamping;
btScalar m_maxSuspensionTravelCm;
btScalar m_maxSuspensionTravel;
btScalar m_frictionSlip;
btScalar m_maxSuspensionForce;

View File

@ -172,7 +172,7 @@ void Physics::update(float dt)
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId();
int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
script_engine->runFunction("void onKartKartCollision(int, int)",
script_engine->runFunction(false, "void onKartKartCollision(int, int)",
[=](asIScriptContext* ctx) {
ctx->SetArgDWord(0, kartid1);
ctx->SetArgDWord(1, kartid2);
@ -201,7 +201,7 @@ void Physics::update(float dt)
if (scripting_function.size() > 0)
{
script_engine->runFunction("void " + scripting_function + "(int, const string, const string)",
script_engine->runFunction(true, "void " + scripting_function + "(int, const string, const string)",
[&](asIScriptContext* ctx) {
ctx->SetArgDWord(0, kartId);
ctx->SetArgObject(1, lib_id_ptr);
@ -274,7 +274,7 @@ void Physics::update(float dt)
std::string scripting_function = obj->getOnItemCollisionFunction();
if (scripting_function.size() > 0)
{
script_engine->runFunction("void " + scripting_function + "(int, int, const string)",
script_engine->runFunction(true, "void " + scripting_function + "(int, int, const string)",
[&](asIScriptContext* ctx) {
ctx->SetArgDWord(0, (int)flyable->getType());
ctx->SetArgDWord(1, flyable->getOwnerId());

View File

@ -175,20 +175,20 @@ namespace Scripting
/** runs the specified script
* \param string scriptName = name of script to run
*/
void ScriptEngine::runFunction(std::string function_name)
void ScriptEngine::runFunction(bool warn_if_not_found, std::string function_name)
{
std::function<void(asIScriptContext*)> callback;
std::function<void(asIScriptContext*)> get_return_value;
runFunction(function_name, callback, get_return_value);
runFunction(warn_if_not_found, function_name, callback, get_return_value);
}
//-----------------------------------------------------------------------------
void ScriptEngine::runFunction(std::string function_name,
void ScriptEngine::runFunction(bool warn_if_not_found, std::string function_name,
std::function<void(asIScriptContext*)> callback)
{
std::function<void(asIScriptContext*)> get_return_value;
runFunction(function_name, callback, get_return_value);
runFunction(warn_if_not_found, function_name, callback, get_return_value);
}
//-----------------------------------------------------------------------------
@ -196,7 +196,7 @@ namespace Scripting
/** runs the specified script
* \param string scriptName = name of script to run
*/
void ScriptEngine::runFunction(std::string function_name,
void ScriptEngine::runFunction(bool warn_if_not_found, std::string function_name,
std::function<void(asIScriptContext*)> callback,
std::function<void(asIScriptContext*)> get_return_value)
{
@ -217,7 +217,10 @@ namespace Scripting
if (func == NULL)
{
Log::debug("Scripting", "Scripting function was not found : %s", function_name.c_str());
if (warn_if_not_found)
Log::warn("Scripting", "Scripting function was not found : %s", function_name.c_str());
else
Log::debug("Scripting", "Scripting function was not found : %s", function_name.c_str());
m_functions_cache[function_name] = NULL; // remember that this function is unavailable
return;
}
@ -233,6 +236,8 @@ namespace Scripting
if (func == NULL)
{
if (warn_if_not_found)
Log::warn("Scripting", "Scripting function was not found : %s", function_name.c_str());
return; // function unavailable
}
@ -425,7 +430,7 @@ namespace Scripting
curr.m_time -= dt;
if (curr.m_time <= 0.0)
{
runFunction("void " + curr.m_callback_name + "()");
runFunction(true, "void " + curr.m_callback_name + "()");
m_pending_timeouts.erase(m_pending_timeouts.begin() + i);
}
}

View File

@ -47,10 +47,10 @@ namespace Scripting
ScriptEngine();
~ScriptEngine();
void runFunction(std::string function_name);
void runFunction(std::string function_name,
void runFunction(bool warn_if_not_found, std::string function_name);
void runFunction(bool warn_if_not_found, std::string function_name,
std::function<void(asIScriptContext*)> callback);
void runFunction(std::string function_name,
void runFunction(bool warn_if_not_found, std::string function_name,
std::function<void(asIScriptContext*)> callback,
std::function<void(asIScriptContext*)> get_return_value);
void evalScript(std::string script_fragment);

View File

@ -101,11 +101,11 @@ namespace Scripting
return StringUtils::wide_to_utf8(out.c_str());
}
/** Runs the script specified by the given string */
/** Runs the script function specified by the given string */
void runScript(const std::string* str)
{
ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
script_engine->runFunction(*str);
script_engine->runFunction(true, *str);
}
/** Generate a random integer value */

View File

@ -0,0 +1,77 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2015 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "tracks/check_cylinder.hpp"
#include <string>
#include <stdio.h>
#include "io/xml_node.hpp"
#include "items/item.hpp"
#include "modes/world.hpp"
#include "race/race_manager.hpp"
CheckCylinder::CheckCylinder(const XMLNode &node, unsigned int index, TriggerItemListener* listener)
: CheckStructure(node, index)
{
m_radius2 = 1;
m_height = 0;
m_listener = listener;
node.get("height", &m_height);
node.get("radius", &m_radius2);
m_radius2 *= m_radius2;
node.get("xyz", &m_center_point);
unsigned int num_karts = race_manager->getNumberOfKarts();
m_is_inside.resize(num_karts);
m_distance2.resize(num_karts);
for (unsigned int i=0; i<num_karts; i++)
{
m_is_inside[i] = false;
}
} // CheckCylinder
// ----------------------------------------------------------------------------
/** True if going from old_pos to new_pos enters or leaves this sphere. This
* function is called from update (of the checkline structure). It also
* updates the flag about which karts are inside
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param kart_id Index of the kart, can be used to store kart specific
* additional data.
*/
bool CheckCylinder::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_id)
{
// TODO: this is the code for a sphere, rewrite for cylinder
Vec3 old_pos_xz(old_pos.x(), 0.0f, old_pos.z());
Vec3 new_pos_xz(new_pos.x(), 0.0f, new_pos.z());
Vec3 center_xz(m_center_point.x(), 0.0f, m_center_point.z());
float old_dist2 = (old_pos_xz - center_xz).length2();
float new_dist2 = (new_pos_xz - center_xz).length2();
m_is_inside[kart_id] = new_dist2<m_radius2;
m_distance2[kart_id] = new_dist2;
// Trigger if the kart goes from outside (or border) to inside,
// or inside ro outside (or border).
bool triggered = (old_dist2>=m_radius2 && new_dist2 < m_radius2) ||
(old_dist2< m_radius2 && new_dist2 >=m_radius2);
if (triggered && m_listener != NULL)
m_listener->onTriggerItemApproached();
return triggered;
} // isTriggered

View File

@ -0,0 +1,69 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2015 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_CHECK_CYLINDER_HPP
#define HEADER_CHECK_CYLINDER_HPP
#include "tracks/check_structure.hpp"
class XMLNode;
class CheckManager;
class TriggerItemListener;
/** This class implements a check sphere that is used to change the ambient
* light if a kart is inside this sphere. Besides a normal radius this
* sphere also has a 2nd 'inner' radius: player karts inside the inner
* radius will have the full new ambient light, karts outside the default
* light, and karts in between will mix the light dependent on distance.
*
* \ingroup tracks
*/
class CheckCylinder : public CheckStructure
{
private:
/** Center of the sphere. */
Vec3 m_center_point;
/** Squared radius of the cylinder. */
float m_radius2;
float m_height;
/** A flag for each kart to indicate if it's inside of the sphere. */
std::vector<bool> m_is_inside;
/** Stores the distance of each kart from the center of this sphere.
* This saves some computations. */
std::vector<float> m_distance2;
TriggerItemListener* m_listener;
public:
CheckCylinder(const XMLNode &node, unsigned int index,
TriggerItemListener* listener);
virtual ~CheckCylinder() {};
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_id);
// ------------------------------------------------------------------------
/** Returns if kart indx is currently inside of the sphere. */
bool isInside(int index) const { return m_is_inside[index]; }
// -------------------------------------------------------------------------
/** Returns the squared distance of kart index from the enter of
* this sphere. */
float getDistance2ForKart(int index) const { return m_distance2[index];}
// -------------------------------------------------------------------------
/** Returns the square of the radius of this sphere. */
float getRadius2() const { return m_radius2; }
}; // CheckCylinder
#endif

View File

@ -55,27 +55,42 @@ void CheckLap::reset(const Track &track)
* is called from update (of the checkline structure).
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param indx Index of the kart, can be used to store kart specific
* \param kart_index Index of the kart, can be used to store kart specific
* additional data.
*/
bool CheckLap::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int indx)
unsigned int kart_index)
{
float track_length = World::getWorld()->getTrack()->getTrackLength();
LinearWorld *lin_world = dynamic_cast<LinearWorld*>(World::getWorld());
World* w = World::getWorld();
LinearWorld* lin_world = dynamic_cast<LinearWorld*>(w);
if (lin_world != NULL)
{
lin_world->getTrackSector(kart_index).setLastTriggeredCheckline(m_index);
}
float track_length = w->getTrack()->getTrackLength();
// Can happen if a non-lap based race mode is used with a scene file that
// has check defined.
if(!lin_world)
return false;
float current_distance = lin_world->getDistanceDownTrackForKart(indx);
bool result =(m_previous_distance[indx]>0.95f*track_length &&
float current_distance = lin_world->getDistanceDownTrackForKart(kart_index);
bool result = (m_previous_distance[kart_index]>0.95f*track_length &&
current_distance<7.0f);
if(UserConfigParams::m_check_debug && result)
if (UserConfigParams::m_check_debug && result)
{
Log::info("CheckLap", "Kart %s crossed start line from %f to %f.",
World::getWorld()->getKart(indx)->getIdent().c_str(),
m_previous_distance[indx], current_distance);
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
m_previous_distance[kart_index], current_distance);
}
m_previous_distance[indx] = current_distance;
m_previous_distance[kart_index] = current_distance;
if (result)
{
LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
if (lw != NULL)
lw->setLastTriggeredCheckline(kart_index, m_index);
}
return result;
} // isTriggered

View File

@ -22,6 +22,7 @@
#include "graphics/irr_driver.hpp"
#include "io/xml_node.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/linear_world.hpp"
#include "modes/world.hpp"
#include "race/race_manager.hpp"
@ -151,14 +152,15 @@ void CheckLine::changeDebugColor(bool is_active)
* additional data.
*/
bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int indx)
unsigned int kart_index)
{
World* w = World::getWorld();
core::vector2df p=new_pos.toIrrVector2d();
bool sign = m_line.getPointOrientation(p)>=0;
bool result;
// If the sign has changed, i.e. the infinite line was crossed somewhere,
// check if the finite line was actually crossed:
if(sign!=m_previous_sign[indx] &&
if (sign != m_previous_sign[kart_index] &&
m_line.intersectWith(core::line2df(old_pos.toIrrVector2d(),
new_pos.toIrrVector2d()),
m_cross_point) )
@ -175,17 +177,24 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
if(World::getWorld()->getNumKarts()>0)
Log::info("CheckLine", "Kart %s crosses line, but wrong height "
"(%f vs %f).",
World::getWorld()->getKart(indx)->getIdent().c_str(),
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
new_pos.getY(), m_min_height);
else
Log::info("CheckLine", "Kart %d crosses line, but wrong height "
"(%f vs %f).",
indx, new_pos.getY(), m_min_height);
kart_index, new_pos.getY(), m_min_height);
}
}
else
result = false;
m_previous_sign[indx] = sign;
m_previous_sign[kart_index] = sign;
if (result)
{
LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
if (lw != NULL)
lw->setLastTriggeredCheckline(kart_index, m_index);
}
return result;
} // isTriggered

View File

@ -59,8 +59,7 @@ void CheckManager::load(const XMLNode &node)
}
else if(type=="check-sphere")
{
AmbientLightSphere *cs = new AmbientLightSphere(*check_node,
i);
CheckSphere *cs = new CheckSphere(*check_node, i);
m_all_checks.push_back(cs);
} // checksphere
else

View File

@ -44,6 +44,7 @@ private:
CheckManager() {m_all_checks.clear();};
~CheckManager();
public:
void add(CheckStructure* strct) { m_all_checks.push_back(strct); }
void load(const XMLNode &node);
void update(float dt);
void reset(const Track &track);

View File

@ -198,13 +198,6 @@ void CheckStructure::changeStatus(const std::vector<int> &indices,
*/
void CheckStructure::trigger(unsigned int kart_index)
{
World* w = World::getWorld();
LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
if (lw != NULL)
{
lw->getTrackSector(kart_index).setLastTriggeredCheckline(m_index);
}
switch(m_check_type)
{
case CT_NEW_LAP :

View File

@ -1200,7 +1200,7 @@ bool Track::loadMainTrack(const XMLNode &root)
unsigned char result = -1;
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
std::function<void(asIScriptContext*)> null_callback;
script_engine->runFunction("bool " + condition + "()", null_callback,
script_engine->runFunction(true, "bool " + condition + "()", null_callback,
[&](asIScriptContext* ctx) { result = ctx->GetReturnByte(); });
if (result == 0)
continue;
@ -1217,7 +1217,7 @@ bool Track::loadMainTrack(const XMLNode &root)
unsigned char result = -1;
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
std::function<void(asIScriptContext*)> null_callback;
script_engine->runFunction("bool " + neg_condition + "()", null_callback,
script_engine->runFunction(true, "bool " + neg_condition + "()", null_callback,
[&](asIScriptContext* ctx) { result = ctx->GetReturnByte(); });
if (result != 0)
continue;
@ -1488,7 +1488,7 @@ void Track::update(float dt)
if (!m_startup_run) // first time running update = good point to run startup script
{
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
script_engine->runFunction("void onStart()");
script_engine->runFunction(false, "void onStart()");
m_startup_run = true;
}
m_track_object_manager->update(dt);
@ -2444,8 +2444,7 @@ bool Track::findGround(AbstractKart *kart)
// length of the suspension with the weight of the kart resting on
// it). On the other hand this initial bouncing looks nice imho
// - so I'll leave it in for now.
float offset = kart->getKartProperties()->getSuspensionRest() +
kart->getKartProperties()->getWheelRadius();
float offset = kart->getKartProperties()->getSuspensionRest();
t.setOrigin(hit_point+Vec3(0, offset, 0) );
kart->getBody()->setCenterOfMassTransform(t);
kart->setTrans(t);

View File

@ -71,9 +71,7 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr,
m_presentation = presentation;
m_is_driveable = false;
m_soccer_ball = false;
m_garage = false;
m_initially_visible = false;
m_distance = 0;
m_type = "";
if (m_interaction != "ghost" && m_interaction != "none" &&
@ -127,9 +125,6 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
m_soccer_ball = false;
xml_node.get("soccer_ball", &m_soccer_ball);
m_garage = false;
m_distance = 0;
std::string type;
xml_node.get("type", &type );
@ -147,7 +142,7 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
unsigned char result = -1;
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
std::function<void(asIScriptContext*)> null_callback;
script_engine->runFunction("bool " + condition + "()", null_callback,
script_engine->runFunction(true, "bool " + condition + "()", null_callback,
[&](asIScriptContext* ctx) { result = ctx->GetReturnByte(); });
if (result == 0)
@ -179,16 +174,9 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
}
else if (type == "action-trigger")
{
std::string m_action;
xml_node.get("action", &m_action);
xml_node.get("distance", &m_distance);
m_name = m_action;
//adds action as name so that it can be found by using getName()
if (m_action == "garage")
{
m_garage = true;
}
std::string action;
xml_node.get("action", &action);
m_name = action; //adds action as name so that it can be found by using getName()
m_presentation = new TrackObjectPresentationActionTrigger(xml_node);
}
else if (type == "billboard")

View File

@ -80,13 +80,9 @@ protected:
bool m_soccer_ball;
bool m_garage;
/** True if a kart can drive on this object. This will */
bool m_is_driveable;
float m_distance;
PhysicalObject* m_physical_object;
ThreeDAnimation* m_animator;
@ -161,10 +157,6 @@ public:
// ------------------------------------------------------------------------
bool isSoccerBall() const { return m_soccer_ball; }
// ------------------------------------------------------------------------
bool isGarage() const { return m_garage; }
// ------------------------------------------------------------------------
float getDistance() const { return m_distance; }
// ------------------------------------------------------------------------
const PhysicalObject* getPhysicalObject() const { return m_physical_object; }
// ------------------------------------------------------------------------
PhysicalObject* getPhysicalObject() { return m_physical_object; }

View File

@ -40,6 +40,9 @@
#include "modes/world.hpp"
#include "scriptengine/script_engine.hpp"
#include "states_screens/dialogs/tutorial_message_dialog.hpp"
#include "tracks/check_cylinder.hpp"
#include "tracks/check_manager.hpp"
#include "tracks/check_sphere.hpp"
#include "tracks/model_definition_loader.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
@ -649,7 +652,7 @@ void TrackObjectPresentationSound::update(float dt)
} // update
// ----------------------------------------------------------------------------
void TrackObjectPresentationSound::onTriggerItemApproached(Item* who)
void TrackObjectPresentationSound::onTriggerItemApproached()
{
if (m_sound != NULL && m_sound->getStatus() != SFXBase::SFX_PLAYING)
{
@ -935,12 +938,40 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
xml_node.get("distance", &trigger_distance);
xml_node.get("action", &m_action );
std::string trigger_type;
xml_node.get("trigger-type", &trigger_type);
if (trigger_type == "point")
{
m_type = TRIGGER_TYPE_POINT;
}
else if (trigger_type == "cylinder")
{
m_type = TRIGGER_TYPE_CYLINDER;
}
else
{
assert(false);
}
m_action_active = true;
if (m_action.size() == 0)
Log::warn("TrackObject", "Action-trigger has no action defined.");
ItemManager::get()->newItem(m_init_xyz, trigger_distance, this);
if (m_type == TRIGGER_TYPE_POINT)
{
// TODO: rewrite as a sphere check structure?
ItemManager::get()->newItem(m_init_xyz, trigger_distance, this);
// CheckManager::get()->add(new CheckSphere(xml_node, 0 /* TODO what is this? */));
}
else if (m_type == TRIGGER_TYPE_CYLINDER)
{
CheckManager::get()->add(new CheckCylinder(xml_node, 0 /* TODO what is this? */, this));
}
else
{
assert(false);
}
} // TrackObjectPresentationActionTrigger
// ----------------------------------------------------------------------------
@ -956,11 +987,12 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
float trigger_distance = distance;
m_action = script_name;
m_action_active = true;
m_type = TRIGGER_TYPE_POINT;
ItemManager::get()->newItem(m_init_xyz, trigger_distance, this);
} // TrackObjectPresentationActionTrigger
// ----------------------------------------------------------------------------
void TrackObjectPresentationActionTrigger::onTriggerItemApproached(Item* who)
void TrackObjectPresentationActionTrigger::onTriggerItemApproached()
{
if (!m_action_active) return;
@ -971,6 +1003,6 @@ void TrackObjectPresentationActionTrigger::onTriggerItemApproached(Item* who)
Camera* camera = Camera::getActiveCamera();
if (camera != NULL && camera->getKart() != NULL)
idKart = camera->getKart()->getWorldKartId();
script_engine->runFunction("void " + m_action + "(int)",
script_engine->runFunction(true, "void " + m_action + "(int)",
[=](asIScriptContext* ctx) { ctx->SetArgDWord(0, idKart); });
} // onTriggerItemApproached

View File

@ -270,7 +270,7 @@ public:
TrackObjectPresentationSound(const XMLNode& xml_node,
scene::ISceneNode* parent);
virtual ~TrackObjectPresentationSound();
virtual void onTriggerItemApproached(Item* who) OVERRIDE;
virtual void onTriggerItemApproached() OVERRIDE;
virtual void update(float dt) OVERRIDE;
virtual void move(const core::vector3df& xyz, const core::vector3df& hpr,
const core::vector3df& scale, bool isAbsoluteCoord) OVERRIDE;
@ -349,6 +349,13 @@ public:
}; // TrackObjectPresentationLight
// ============================================================================
enum ActionTriggerType
{
TRIGGER_TYPE_POINT = 0,
TRIGGER_TYPE_CYLINDER = 1
};
/** \ingroup tracks
* A track object representation that consists of an action trigger
*/
@ -361,6 +368,8 @@ private:
bool m_action_active;
ActionTriggerType m_type;
public:
TrackObjectPresentationActionTrigger(const XMLNode& xml_node);
TrackObjectPresentationActionTrigger(const core::vector3df& xyz,
@ -369,7 +378,7 @@ public:
virtual ~TrackObjectPresentationActionTrigger() {}
virtual void onTriggerItemApproached(Item* who) OVERRIDE;
virtual void onTriggerItemApproached() OVERRIDE;
// ------------------------------------------------------------------------
/** Reset the trigger (i.e. sets it to active again). */
virtual void reset() OVERRIDE { m_action_active = true; }