Use normal particle terrain to make water splash; proper location
for water splashes is now being detected. Note: existing tracks need to be updated. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7706 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
9da63504cc
commit
66ff37eb80
@ -502,9 +502,3 @@ void Camera::activate()
|
||||
} // activate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Camera::setFallMode(bool mode)
|
||||
{
|
||||
if (mode) m_mode = CM_FALLING;
|
||||
else m_mode = CM_NORMAL;
|
||||
}
|
||||
|
@ -195,10 +195,6 @@ public:
|
||||
|
||||
/** Returns the scaling in x/y direction for this camera. */
|
||||
const core::vector2df& getScaling() const {return m_scaling; }
|
||||
|
||||
/** In "fall mode", the camera stays up and looks down at the falling kart
|
||||
(mainly to avoid following the kart underwater) */
|
||||
void setFallMode(bool fallMode);
|
||||
|
||||
/** Returns the camera scene node. */
|
||||
scene::ICameraSceneNode *getCameraSceneNode()
|
||||
|
@ -60,10 +60,17 @@ Material::Material(const XMLNode *node, int index)
|
||||
node->get("light", &m_lighting );
|
||||
node->get("sphere", &m_sphere_map );
|
||||
node->get("friction", &m_friction );
|
||||
node->get("reset", &m_resetter );
|
||||
node->get("below-surface", &m_below_surface );
|
||||
node->get("falling-effect", &m_falling_effect );
|
||||
// A terrain with falling effect has to force a reset
|
||||
// since. So to make it easier for artists, force
|
||||
// the reset flag in this case.
|
||||
if(m_falling_effect)
|
||||
m_resetter=true;
|
||||
node->get("surface", &m_surface );
|
||||
node->get("ignore", &m_ignore );
|
||||
node->get("reset", &m_resetter );
|
||||
|
||||
node->get("additive", &m_add );
|
||||
node->get("max-speed", &m_max_speed_fraction);
|
||||
node->get("slowdown-time", &m_slowdown_time );
|
||||
@ -162,6 +169,7 @@ void Material::init(unsigned int index)
|
||||
m_sphere_map = false;
|
||||
m_friction = 1.0f;
|
||||
m_below_surface = false;
|
||||
m_falling_effect = false;
|
||||
m_surface = false;
|
||||
m_ignore = false;
|
||||
m_resetter = false;
|
||||
|
@ -60,6 +60,10 @@ private:
|
||||
* the water is marked as 'm_below_surface', which will then trigger a raycast
|
||||
* up to find the position of the actual water surface. */
|
||||
bool m_below_surface;
|
||||
|
||||
/** If a kart is falling over a material with this flag set, it
|
||||
* will trigger the special camera fall effect. */
|
||||
bool m_falling_effect;
|
||||
/** A material that is a surface only, i.e. the karts can fall through
|
||||
* but the information is still needed (for GFX mostly). An example is
|
||||
* a water surface: karts can drive while partly in water (so the water
|
||||
@ -191,6 +195,10 @@ public:
|
||||
*/
|
||||
const ParticleKind* getParticlesWhen(ParticleConditions cond) const { return m_particles_effects[cond]; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if a kart falling over this kind of material triggers
|
||||
* the special falling camera. */
|
||||
bool hasFallingEffect() const {return m_falling_effect; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the zipper parametersfor the current material. */
|
||||
void getZipperParameter(float *zipper_max_speed_increase,
|
||||
|
@ -86,7 +86,7 @@ public:
|
||||
|
||||
// ============================================================================
|
||||
ParticleEmitter::ParticleEmitter(const ParticleKind* type,
|
||||
const core::vector3df &position,
|
||||
const Vec3 &position,
|
||||
scene::ISceneNode* parent)
|
||||
: m_position(position)
|
||||
{
|
||||
@ -167,11 +167,13 @@ void ParticleEmitter::setCreationRate(float f)
|
||||
} // setCreationRate
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ParticleEmitter::setPosition(const core::vector3df &pos)
|
||||
/** Sets the position of the particle emitter.
|
||||
* \param pos The position for the particle emitter.
|
||||
*/
|
||||
void ParticleEmitter::setPosition(const Vec3 &pos)
|
||||
{
|
||||
m_node->setPosition(pos);
|
||||
}
|
||||
m_node->setPosition(pos.toIrrVector());
|
||||
} // setPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -220,7 +222,7 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
|
||||
video::SMaterial& mat0 = m_node->getMaterial(0);
|
||||
|
||||
m_node->setPosition(m_position);
|
||||
m_node->setPosition(m_position.toIrrVector());
|
||||
material->setMaterialProperties(&mat0);
|
||||
m_node->setMaterialTexture(0, material->getTexture());
|
||||
|
||||
@ -238,9 +240,6 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
lifeTimeMin, lifeTimeMax,
|
||||
m_particle_type->getAngleSpread() /* angle */
|
||||
);
|
||||
|
||||
//irr_driver->getSceneManager()->addCubeSceneNode(0.1f, m_parent, -1, m_position);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -258,11 +257,7 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
type->getMinColor(), type->getMaxColor(),
|
||||
lifeTimeMin, lifeTimeMax,
|
||||
m_particle_type->getAngleSpread() /* angle */
|
||||
);
|
||||
|
||||
//irr_driver->getSceneManager()->addCubeSceneNode(2.0f, m_parent, -1, m_position, core::vector3df(0, 0, 0) /* rotation */,
|
||||
// core::vector3df(box_size_x*2, box_size_y*2, box_size_z*2));
|
||||
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,12 @@
|
||||
#ifndef HEADER_SMOKE_HPP
|
||||
#define HEADER_SMOKE_HPP
|
||||
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include "irrlicht.h"
|
||||
using namespace irr;
|
||||
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
class Material;
|
||||
class ParticleKind;
|
||||
|
||||
@ -39,7 +40,7 @@ private:
|
||||
/** Irrlicht's particle systems. */
|
||||
scene::IParticleSystemSceneNode *m_node;
|
||||
|
||||
core::vector3df m_position;
|
||||
Vec3 m_position;
|
||||
|
||||
scene::ISceneNode* m_parent;
|
||||
|
||||
@ -54,13 +55,13 @@ private:
|
||||
public:
|
||||
|
||||
ParticleEmitter (const ParticleKind* type,
|
||||
const core::vector3df &position,
|
||||
const Vec3 &position,
|
||||
scene::ISceneNode* parent = NULL);
|
||||
virtual ~ParticleEmitter();
|
||||
virtual void update ();
|
||||
void setCreationRate(float f);
|
||||
|
||||
void setPosition(const core::vector3df &pos);
|
||||
void setPosition(const Vec3 &pos);
|
||||
|
||||
const ParticleKind* getParticlesInfo() const { return m_particle_type; }
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "karts/emergency_animation.hpp"
|
||||
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/stars.hpp"
|
||||
#include "karts/kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
@ -123,6 +124,9 @@ void EmergencyAnimation::forceRescue(bool is_auto_rescue)
|
||||
world->kartHit(m_kart->getWorldKartId());
|
||||
}
|
||||
|
||||
// Reset camera in case that it was in falling mode before.
|
||||
if(m_kart->getCamera())
|
||||
m_kart->getCamera()->setMode(Camera::CM_NORMAL);
|
||||
} // forceRescue
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -205,6 +209,7 @@ void EmergencyAnimation::update(float dt)
|
||||
// here, and again in reset (e.g. when restarting the race) if
|
||||
// m_eliminated is still true.
|
||||
m_eliminated = false;
|
||||
m_kart->getCamera()->setMode(Camera::CM_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,6 @@ Kart::Kart (const std::string& ident, Track* track, int position,
|
||||
m_shadow_enabled = false;
|
||||
m_shadow = NULL;
|
||||
m_terrain_particles = NULL;
|
||||
m_water_splash_system = NULL;
|
||||
m_nitro = NULL;
|
||||
m_slipstream = NULL;
|
||||
m_skidmarks = NULL;
|
||||
@ -336,7 +335,6 @@ Kart::~Kart()
|
||||
if(m_terrain_sound) sfx_manager->deleteSFX(m_terrain_sound);
|
||||
if(m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound);
|
||||
if(m_terrain_particles) delete m_terrain_particles;
|
||||
if(m_water_splash_system) delete m_water_splash_system;
|
||||
if(m_nitro) delete m_nitro;
|
||||
if(m_slipstream) delete m_slipstream;
|
||||
if(m_rain) delete m_rain;
|
||||
@ -752,7 +750,6 @@ void Kart::update(float dt)
|
||||
if (UserConfigParams::m_graphical_effects)
|
||||
{
|
||||
if (m_terrain_particles) m_terrain_particles->update();
|
||||
if (m_water_splash_system) m_water_splash_system->update();
|
||||
if (m_rain)
|
||||
{
|
||||
m_rain->setPosition( getCamera()->getCameraSceneNode()->getPosition() );
|
||||
@ -805,8 +802,9 @@ void Kart::update(float dt)
|
||||
{
|
||||
m_body->getBroadphaseHandle()->m_collisionFilterGroup = old_group;
|
||||
}
|
||||
handleMaterialGFX();
|
||||
const Material* material=TerrainInfo::getMaterial();
|
||||
if (getHoT()==Track::NOHIT) // kart falling off the track
|
||||
if (!material) // kart falling off the track
|
||||
{
|
||||
// let kart fall a bit before rescuing
|
||||
const Vec3 *min, *max;
|
||||
@ -814,61 +812,9 @@ void Kart::update(float dt)
|
||||
if(min->getY() - getXYZ().getY() > 17)
|
||||
forceRescue();
|
||||
}
|
||||
|
||||
// Sometimes the material can be 0. This can happen if a kart is above
|
||||
// another kart (e.g. mass collision, or one kart falling on another
|
||||
// kart). Bullet does not have any triangle information in this case,
|
||||
// and so material can not be set. In this case it is simply ignored
|
||||
// since it can't hurt (material is only used for friction, zipper and
|
||||
// rescue, so those things are not triggered till the kart is on the
|
||||
// track again)
|
||||
else if(material)
|
||||
else
|
||||
{
|
||||
// If a terrain specific sfx is already being played, when a new
|
||||
// terrain is entered, an old sfx should be finished (once, not
|
||||
// looped anymore of course). The m_terrain_sound is then copied
|
||||
// to a m_previous_terrain_sound, for which looping is disabled.
|
||||
// In case that three sfx needed to be played (i.e. a previous is
|
||||
// playing, a current is playing, and a new terrain with sfx is
|
||||
// entered), the oldest (previous) sfx is stopped and deleted.
|
||||
if(getLastMaterial()!=material)
|
||||
{
|
||||
// First stop any previously playing terrain sound
|
||||
// and remove it, sp that m_previous_terrain_sound
|
||||
// can be used again.
|
||||
if(m_previous_terrain_sound)
|
||||
{
|
||||
sfx_manager->deleteSFX(m_previous_terrain_sound);
|
||||
}
|
||||
m_previous_terrain_sound = m_terrain_sound;
|
||||
if(m_previous_terrain_sound)
|
||||
m_previous_terrain_sound->setLoop(false);
|
||||
|
||||
const std::string s = material->getSFXName();
|
||||
if(s!="")
|
||||
{
|
||||
m_terrain_sound = sfx_manager->createSoundSource(s);
|
||||
m_terrain_sound->play();
|
||||
m_terrain_sound->setLoop(true);
|
||||
}
|
||||
else
|
||||
m_terrain_sound = NULL;
|
||||
}
|
||||
if(m_previous_terrain_sound &&
|
||||
m_previous_terrain_sound->getStatus()==SFXManager::SFX_STOPPED)
|
||||
{
|
||||
// We don't modify the position of m_previous_terrain_sound
|
||||
// anymore, so that it keeps on playing at the place where the
|
||||
// kart left the material.
|
||||
sfx_manager->deleteSFX(m_previous_terrain_sound);
|
||||
m_previous_terrain_sound = NULL;
|
||||
}
|
||||
if(m_terrain_sound)
|
||||
{
|
||||
m_terrain_sound->position(getXYZ());
|
||||
material->setSFXSpeed(m_terrain_sound, m_speed);
|
||||
}
|
||||
|
||||
handleMaterialSFX(material);
|
||||
if (material->isReset() && isOnGround()) forceRescue();
|
||||
else if(material->isZipper() && isOnGround()) handleZipper(material);
|
||||
else
|
||||
@ -921,6 +867,164 @@ void Kart::update(float dt)
|
||||
}
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Plays any terrain specific sound effect.
|
||||
*/
|
||||
void Kart::handleMaterialSFX(const Material *material)
|
||||
{
|
||||
// If a terrain specific sfx is already being played, when a new
|
||||
// terrain is entered, an old sfx should be finished (once, not
|
||||
// looped anymore of course). The m_terrain_sound is then copied
|
||||
// to a m_previous_terrain_sound, for which looping is disabled.
|
||||
// In case that three sfx needed to be played (i.e. a previous is
|
||||
// playing, a current is playing, and a new terrain with sfx is
|
||||
// entered), the oldest (previous) sfx is stopped and deleted.
|
||||
if(getLastMaterial()!=material)
|
||||
{
|
||||
// First stop any previously playing terrain sound
|
||||
// and remove it, sp that m_previous_terrain_sound
|
||||
// can be used again.
|
||||
if(m_previous_terrain_sound)
|
||||
{
|
||||
sfx_manager->deleteSFX(m_previous_terrain_sound);
|
||||
}
|
||||
m_previous_terrain_sound = m_terrain_sound;
|
||||
if(m_previous_terrain_sound)
|
||||
m_previous_terrain_sound->setLoop(false);
|
||||
|
||||
const std::string s = material->getSFXName();
|
||||
if(s!="")
|
||||
{
|
||||
m_terrain_sound = sfx_manager->createSoundSource(s);
|
||||
m_terrain_sound->play();
|
||||
m_terrain_sound->setLoop(true);
|
||||
}
|
||||
else
|
||||
m_terrain_sound = NULL;
|
||||
}
|
||||
if(m_previous_terrain_sound &&
|
||||
m_previous_terrain_sound->getStatus()==SFXManager::SFX_STOPPED)
|
||||
{
|
||||
// We don't modify the position of m_previous_terrain_sound
|
||||
// anymore, so that it keeps on playing at the place where the
|
||||
// kart left the material.
|
||||
sfx_manager->deleteSFX(m_previous_terrain_sound);
|
||||
m_previous_terrain_sound = NULL;
|
||||
}
|
||||
if(m_terrain_sound)
|
||||
{
|
||||
m_terrain_sound->position(getXYZ());
|
||||
material->setSFXSpeed(m_terrain_sound, m_speed);
|
||||
}
|
||||
|
||||
} // handleMaterialSFX
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Handles material specific sfx, mostly particle effects. Particle
|
||||
* effects can be triggered by two different situations: either
|
||||
* because a kart drives on top of a terrain with a special effect,
|
||||
* or because the kart is driving or falling under a surface (e.g.
|
||||
* water), and the terrain effect is coming from that surface. Those
|
||||
* effects are exclusive - you either get the effect from the terrain
|
||||
* you are driving on, or the effect from a surface the kart is
|
||||
* (partially) under. The surface effect is triggered, if either the
|
||||
* kart is falling, or if the surface the kart is driving on has
|
||||
* the 'isBelowSurface' property set.
|
||||
*/
|
||||
void Kart::handleMaterialGFX()
|
||||
{
|
||||
// Nothing to do if there are no particles.
|
||||
if (!m_terrain_particles) return;
|
||||
|
||||
const Material *material = getMaterial();
|
||||
|
||||
// First test: give the terrain effect, if the kart is
|
||||
// on top of a surface (i.e. not falling), actually touching
|
||||
// something with the wheels, and the material has not the
|
||||
// below surface property set.
|
||||
if(material && isOnGround() && !material->isBelowSurface())
|
||||
{
|
||||
Vec3 xyz;
|
||||
m_wheel_toggle = 1 - m_wheel_toggle;
|
||||
const btWheelInfo &wi =
|
||||
getVehicle()->getWheelInfo(2 + m_wheel_toggle);
|
||||
xyz = wi.m_raycastInfo.m_contactPointWS;
|
||||
// FIXME: the X position is not yet always accurate.
|
||||
xyz += Vec3(0.06f * (m_wheel_toggle ? +1 : -1),
|
||||
0,
|
||||
0.06f);
|
||||
// Get the appropriate particle data depending on
|
||||
// wether the kart is skidding or driving.
|
||||
const ParticleKind* pk =
|
||||
material->getParticlesWhen(m_skidding > 1.0f
|
||||
? Material::EMIT_ON_SKID
|
||||
: Material::EMIT_ON_DRIVE);
|
||||
if(!pk)
|
||||
{
|
||||
// Disable potentially running particle effects
|
||||
m_terrain_particles->setCreationRate(0);
|
||||
return; // no particle effect, return
|
||||
}
|
||||
|
||||
// Now compute the particle creation rate:
|
||||
float rate = 0;
|
||||
if(m_skidding > 1.0f)
|
||||
{
|
||||
rate = fabsf(m_controls.m_steer) > 0.8 ? m_skidding - 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float speed = fabsf(getSpeed());
|
||||
rate = (speed>=0.5f) ? speed/m_kart_properties->getMaxSpeed()
|
||||
: 0;
|
||||
}
|
||||
|
||||
float create = pk->getMinRate()*(1-rate) + pk->getMaxRate()*rate;
|
||||
m_terrain_particles->setParticleType(pk);
|
||||
m_terrain_particles->setCreationRate(create);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now the kart is either falling, or driving on a terrain which
|
||||
// has the 'below surface' flag set. Detect if there is a surface
|
||||
// on top of the kart.
|
||||
if(material->hasFallingEffect() && m_camera)
|
||||
{
|
||||
m_camera->setMode(Camera::CM_FALLING);
|
||||
}
|
||||
|
||||
// Use the middle of the contact points of the two rear wheels
|
||||
// as the point from which to cast the ray upwards
|
||||
const btWheelInfo::RaycastInfo &ri2 =
|
||||
getVehicle()->getWheelInfo(2).m_raycastInfo;
|
||||
const btWheelInfo::RaycastInfo &ri3 =
|
||||
getVehicle()->getWheelInfo(3).m_raycastInfo;
|
||||
Vec3 from = (ri2.m_contactPointWS + ri3.m_contactPointWS)*0.5f;
|
||||
Vec3 xyz;
|
||||
const Material *surface_material;
|
||||
if(!getSurfaceInfo(from, &xyz, &surface_material))
|
||||
{
|
||||
m_terrain_particles->setCreationRate(0);
|
||||
return;
|
||||
}
|
||||
const ParticleKind *pk =
|
||||
surface_material->getParticlesWhen(Material::EMIT_ON_DRIVE);
|
||||
if(pk && !m_flying)
|
||||
{
|
||||
m_terrain_particles->setParticleType(pk);
|
||||
m_terrain_particles->setPosition(xyz.toIrrVector());
|
||||
const float speed = fabsf(getSpeed());
|
||||
float rate = (speed>=0.5f) ? speed/m_kart_properties->getMaxSpeed()
|
||||
: 0;
|
||||
|
||||
float create = pk->getMinRate()*(1-rate) + pk->getMaxRate()*rate;
|
||||
m_terrain_particles->setCreationRate(create);
|
||||
}
|
||||
//if (m_camera != NULL) m_camera->setFallMode(true);
|
||||
//m_camera->setFallMode(false);
|
||||
|
||||
} // handleMaterialGFX
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Kart::setCamera(Camera *camera)
|
||||
@ -1365,18 +1469,6 @@ void Kart::updatePhysics(float dt)
|
||||
|
||||
m_vehicle->enableSliding(enable_skidding);
|
||||
|
||||
|
||||
/*
|
||||
// debug prints
|
||||
static float f = 0.0f;
|
||||
f += dt;
|
||||
if (f > 0.5f)
|
||||
{
|
||||
f -= 0.5f;
|
||||
printf("[%s] %f %f --> friction = %f\n", m_kart_properties->getIdent().c_str(), getPitch(), getRoll(), friction);
|
||||
}
|
||||
*/
|
||||
|
||||
float steering = getMaxSteerAngle() * m_controls.m_steer*m_skidding;
|
||||
|
||||
m_vehicle->setSteeringValue(steering, 0);
|
||||
@ -1492,7 +1584,7 @@ void Kart::loadData(RaceManager::KartType type, Track* track, bool animatedModel
|
||||
// gives the position of the wheels on the ground in world coordinates.
|
||||
// So it's easier not to move the particle system with the kart, and set
|
||||
// the position directly from the wheel coordinates.
|
||||
core::vector3df position(-getKartWidth()*0.35f, 0.06f, -getKartLength()*0.5f);
|
||||
Vec3 position(-getKartWidth()*0.35f, 0.06f, -getKartLength()*0.5f);
|
||||
m_terrain_particles = new ParticleEmitter(ParticleKindManager::get()->getParticles("smoke.xml"),
|
||||
position);
|
||||
}
|
||||
@ -1506,14 +1598,8 @@ void Kart::loadData(RaceManager::KartType type, Track* track, bool animatedModel
|
||||
{
|
||||
m_rain = new Rain((m_camera != NULL ? m_camera->getCameraSceneNode() : NULL), NULL);
|
||||
}
|
||||
|
||||
//m_water_splash_system = new WaterSplash(this);
|
||||
|
||||
m_water_splash_system = new ParticleEmitter(ParticleKindManager::get()->getParticles("splash.xml"),
|
||||
core::vector3df(0.0f, 0.0f, 0.0f), getNode());
|
||||
m_water_splash_system->setCreationRate(0);
|
||||
|
||||
core::vector3df position(0, getKartHeight()*0.35f, -getKartLength()*0.35f);
|
||||
|
||||
Vec3 position(0, getKartHeight()*0.35f, -getKartLength()*0.35f);
|
||||
|
||||
try
|
||||
{
|
||||
@ -1606,136 +1692,6 @@ void Kart::updateGraphics(const Vec3& offset_xyz,
|
||||
-m_kart_model->getWheelGraphicsPosition(0).getY() );
|
||||
center_shift.setY(y);
|
||||
|
||||
if (m_terrain_particles)
|
||||
{
|
||||
const Material* material = getMaterial();
|
||||
|
||||
if (material != NULL)
|
||||
{
|
||||
if (m_skidding > 1.0f)
|
||||
{
|
||||
const ParticleKind* pk = material->getParticlesWhen(Material::EMIT_ON_SKID);
|
||||
if (pk != NULL && isOnGround())
|
||||
{
|
||||
m_terrain_particles->setParticleType(pk);
|
||||
|
||||
if (fabsf(m_controls.m_steer) > 0.8 && isOnGround())
|
||||
{
|
||||
float rate = m_skidding - 1;
|
||||
m_terrain_particles->setCreationRate(pk->getMinRate() + rate*(pk->getMaxRate() - pk->getMinRate()));
|
||||
|
||||
m_wheel_toggle = 1 - m_wheel_toggle;
|
||||
const btWheelInfo &wi = getVehicle()->getWheelInfo(2 + m_wheel_toggle);
|
||||
Vec3 c = wi.m_raycastInfo.m_contactPointWS;
|
||||
|
||||
// FIXME: the X position is not yet always accurate.
|
||||
m_terrain_particles->setPosition(core::vector3df(c.getX() + 0.06f * (m_wheel_toggle ? +1 : -1),
|
||||
c.getY(),
|
||||
c.getZ() + 0.06f));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_terrain_particles->setCreationRate(0.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_terrain_particles->setCreationRate(0);
|
||||
}
|
||||
}
|
||||
else // not skidding
|
||||
{
|
||||
const ParticleKind* pk = material->getParticlesWhen(Material::EMIT_ON_DRIVE);
|
||||
if (pk != NULL && isOnGround())
|
||||
{
|
||||
//printf("Setting DRIVING particles\n");
|
||||
m_terrain_particles->setParticleType(pk);
|
||||
|
||||
m_wheel_toggle = 1 - m_wheel_toggle;
|
||||
const btWheelInfo &wi = getVehicle()->getWheelInfo(2 + m_wheel_toggle);
|
||||
Vec3 c = wi.m_raycastInfo.m_contactPointWS;
|
||||
|
||||
// FIXME: the X position is not yet always accurate.
|
||||
m_terrain_particles->setPosition(core::vector3df(c.getX() + 0.06f * (m_wheel_toggle ? +1 : -1),
|
||||
c.getY(),
|
||||
c.getZ() + 0.06f));
|
||||
|
||||
const float speed = fabsf(getSpeed());
|
||||
if (speed < 0.5f)
|
||||
{
|
||||
m_terrain_particles->setCreationRate(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
float rate = (speed/m_kart_properties->getMaxSpeed());
|
||||
m_terrain_particles->setCreationRate(pk->getMinRate() + rate*(pk->getMaxRate() - pk->getMinRate()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("No DRIVING particles\n");
|
||||
m_terrain_particles->setCreationRate(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_terrain_particles->setCreationRate(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_water_splash_system)
|
||||
{
|
||||
const Material* m = getMaterial();
|
||||
if (m != NULL)
|
||||
{
|
||||
const float hot = getHoT();
|
||||
|
||||
if (m->hasWaterSplash() && hot != Track::NOHIT && !m_flying)
|
||||
{
|
||||
const float hat = getXYZ().getY() - hot;
|
||||
#ifdef NOT_TESTED_YET
|
||||
if(m->isBelowSurface())
|
||||
{
|
||||
Vec3 pos;
|
||||
if(getSurfacePosition(&pos))
|
||||
{
|
||||
m_water_splash_system->setPosition(pos.toIrrVector());
|
||||
m_water_splash_system->setCreationRate(
|
||||
(float)m_water_splash_system->getParticlesInfo()->getMaxRate()
|
||||
);
|
||||
}
|
||||
} // m->isBelowSurface
|
||||
#endif
|
||||
// TODO: don't hardcode height, get from exporter
|
||||
if (hat < 4.0f && hat > 2.0f)
|
||||
{
|
||||
m_water_splash_system->setCreationRate(
|
||||
(float)m_water_splash_system->getParticlesInfo()->getMaxRate()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_camera != NULL) m_camera->setFallMode(true);
|
||||
m_water_splash_system->setCreationRate(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_camera != NULL && m_camera->getMode() == Camera::CM_FALLING)
|
||||
{
|
||||
m_camera->setFallMode(false);
|
||||
}
|
||||
|
||||
m_water_splash_system->setCreationRate(0);
|
||||
}
|
||||
}
|
||||
|
||||
//float f = getMaterial() && getMaterial()->hasWaterSplash() && isOnGround()
|
||||
// ? sqrt(getSpeed())*40.0f
|
||||
// : 0.0f;
|
||||
//m_water_splash_system->setCreationRate(f);
|
||||
}
|
||||
if (m_nitro)
|
||||
{
|
||||
// fabs(speed) is important, otherwise the negative number will
|
||||
|
@ -137,10 +137,7 @@ private:
|
||||
bool m_shadow_enabled;
|
||||
|
||||
/** Particle emitter used for terrain-specific effects (including but not limited too skidding). */
|
||||
ParticleEmitter *m_terrain_particles;
|
||||
|
||||
/** Water splash when driving in water. */
|
||||
ParticleEmitter *m_water_splash_system;
|
||||
ParticleEmitter *m_terrain_particles;
|
||||
|
||||
/** Graphical effect when using a nitro. */
|
||||
ParticleEmitter *m_nitro;
|
||||
@ -182,6 +179,8 @@ private:
|
||||
float m_time_last_crash;
|
||||
|
||||
void updatePhysics(float dt);
|
||||
void handleMaterialSFX(const Material *material);
|
||||
void handleMaterialGFX();
|
||||
|
||||
protected:
|
||||
const KartProperties *m_kart_properties;
|
||||
|
@ -212,6 +212,12 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
|
||||
btVector3 *xyz, const Material **material,
|
||||
btVector3 *normal) const
|
||||
{
|
||||
if(!m_collision_shape)
|
||||
{
|
||||
*material=NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
btTransform trans_from;
|
||||
trans_from.setIdentity();
|
||||
trans_from.setOrigin(from);
|
||||
@ -264,13 +270,17 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
|
||||
{
|
||||
*xyz = ray_callback.m_hitPointWorld;
|
||||
*material = ray_callback.m_material;
|
||||
*normal = ray_callback.m_hitNormalWorld;
|
||||
normal->normalize();
|
||||
if(normal)
|
||||
{
|
||||
*normal = ray_callback.m_hitNormalWorld;
|
||||
normal->normalize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*material = NULL;
|
||||
normal->setValue(0, 1, 0);
|
||||
if(normal)
|
||||
normal->setValue(0, 1, 0);
|
||||
}
|
||||
return ray_callback.hasHit();
|
||||
|
||||
|
@ -58,45 +58,21 @@ void TerrainInfo::update(const Vec3& pos)
|
||||
} // update
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** If the raycast indicated that the kart is 'under something' (i.e. a
|
||||
/** Does a raycast upwards from the given position
|
||||
If the raycast indicated that the kart is 'under something' (i.e. a
|
||||
* specially marked terrain), to another raycast up to detect under whic
|
||||
* mesh the kart is. This is using the special gfx effect mesh only.
|
||||
* This is used e.g. to detect if a kart is under water, and then to
|
||||
* get the proper position for water effects. Note that the TerrainInfo
|
||||
* objects keeps track of the previous raycast position.
|
||||
*/
|
||||
bool TerrainInfo::getSurfacePosition(Vec3 *position)
|
||||
bool TerrainInfo::getSurfaceInfo(const Vec3 &from, Vec3 *position,
|
||||
const Material **material)
|
||||
{
|
||||
if(m_material && m_material->isBelowSurface())
|
||||
{
|
||||
btTransform from;
|
||||
from.setIdentity();
|
||||
from.setOrigin(m_hit_point);
|
||||
btTransform to;
|
||||
to.setIdentity();
|
||||
to.setOrigin(m_hit_point+btVector3(0, 10000.0f, 0));
|
||||
btTransform world_trans;
|
||||
world_trans.setIdentity();
|
||||
|
||||
btCollisionWorld::ClosestRayResultCallback
|
||||
result(from.getOrigin(), to.getOrigin());
|
||||
|
||||
const btCollisionShape &shape =
|
||||
World::getWorld()->getTrack()->getGFXEffectMesh().getCollisionShape();
|
||||
btCollisionObject col_obj;
|
||||
btTransform bt;
|
||||
bt.setIdentity();
|
||||
col_obj.setWorldTransform(bt);
|
||||
btCollisionWorld::rayTestSingle(from, to, &col_obj, &shape,
|
||||
world_trans, result);
|
||||
if(result.hasHit())
|
||||
{
|
||||
*position = result.m_hitPointWorld;
|
||||
}
|
||||
return result.hasHit();
|
||||
}
|
||||
return false;
|
||||
} // getSurfacePosition
|
||||
Vec3 to=from+Vec3(0, 10000, 0);
|
||||
const TriangleMesh &tm = World::getWorld()->getTrack()->getGFXEffectMesh();
|
||||
return tm.castRay(from, to, position, material);
|
||||
} // getSurfaceInfo
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Returns the pitch of the terrain depending on the heading
|
||||
|
@ -38,8 +38,6 @@ private:
|
||||
const Material *m_last_material;
|
||||
/** The point that was hit. */
|
||||
Vec3 m_hit_point;
|
||||
/** Position of last raycast. */
|
||||
Vec3 m_last_pos;
|
||||
|
||||
public:
|
||||
TerrainInfo();
|
||||
@ -47,7 +45,8 @@ public:
|
||||
virtual ~TerrainInfo() {};
|
||||
|
||||
virtual void update(const Vec3 &pos);
|
||||
bool getSurfacePosition(Vec3 *position);
|
||||
bool getSurfaceInfo(const Vec3 &from, Vec3 *position,
|
||||
const Material **m);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the height of the terrain. we're currently above */
|
||||
|
@ -437,12 +437,16 @@ void Track::convertTrackToBullet(scene::ISceneNode *node)
|
||||
{
|
||||
std::string image = std::string(core::stringc(t->getName()).c_str());
|
||||
material=material_manager->getMaterial(StringUtils::getBasename(image));
|
||||
if(material->isIgnore()) continue;
|
||||
// Special gfx meshes will not be stored as a normal physics body,
|
||||
// but converted to a collision body only, so that ray tests
|
||||
// against them can be done.
|
||||
if(material->isSurface())
|
||||
tmesh = m_gfx_effect_mesh;
|
||||
// A material which is a surface must be converted,
|
||||
// even if it's marked as ignore. So only ignore
|
||||
// non-surface materials.
|
||||
else if(material->isIgnore())
|
||||
continue;
|
||||
}
|
||||
|
||||
u16 *mbIndices = mb->getIndices();
|
||||
|
Loading…
Reference in New Issue
Block a user