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:
hikerstk 2011-02-15 21:12:24 +00:00
parent 9da63504cc
commit 66ff37eb80
13 changed files with 233 additions and 282 deletions

View File

@ -502,9 +502,3 @@ void Camera::activate()
} // activate
// ----------------------------------------------------------------------------
void Camera::setFallMode(bool mode)
{
if (mode) m_mode = CM_FALLING;
else m_mode = CM_NORMAL;
}

View File

@ -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()

View File

@ -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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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; }

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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 */

View File

@ -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();