diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 111a297ca..f1b80be81 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -502,9 +502,3 @@ void Camera::activate() } // activate // ---------------------------------------------------------------------------- - -void Camera::setFallMode(bool mode) -{ - if (mode) m_mode = CM_FALLING; - else m_mode = CM_NORMAL; -} diff --git a/src/graphics/camera.hpp b/src/graphics/camera.hpp index 8be7b415e..d4ade77f8 100644 --- a/src/graphics/camera.hpp +++ b/src/graphics/camera.hpp @@ -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() diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index 0f7d4b381..5fa100d7f 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -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; diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index 010e23ee1..0d7138d7a 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -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, diff --git a/src/graphics/particle_emitter.cpp b/src/graphics/particle_emitter.cpp index 45d694431..083e2b68b 100644 --- a/src/graphics/particle_emitter.cpp +++ b/src/graphics/particle_emitter.cpp @@ -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; } diff --git a/src/graphics/particle_emitter.hpp b/src/graphics/particle_emitter.hpp index 2788a7c24..e5a13ecae 100644 --- a/src/graphics/particle_emitter.hpp +++ b/src/graphics/particle_emitter.hpp @@ -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; } diff --git a/src/karts/emergency_animation.cpp b/src/karts/emergency_animation.cpp index 553fdcc86..1de4500b8 100644 --- a/src/karts/emergency_animation.cpp +++ b/src/karts/emergency_animation.cpp @@ -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; } diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 0f1ac0326..4ed64879f 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -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 diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 123c7ad7d..95169f454 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -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; diff --git a/src/physics/triangle_mesh.cpp b/src/physics/triangle_mesh.cpp index 0255dfc44..c07a037a4 100644 --- a/src/physics/triangle_mesh.cpp +++ b/src/physics/triangle_mesh.cpp @@ -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(); diff --git a/src/tracks/terrain_info.cpp b/src/tracks/terrain_info.cpp index 03f40e477..db2c82865 100644 --- a/src/tracks/terrain_info.cpp +++ b/src/tracks/terrain_info.cpp @@ -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 diff --git a/src/tracks/terrain_info.hpp b/src/tracks/terrain_info.hpp index 552779bca..a884c1243 100644 --- a/src/tracks/terrain_info.hpp +++ b/src/tracks/terrain_info.hpp @@ -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 */ diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 58ed08b70..eb7cec43b 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -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();