Start to support driving (and rescuing) on physical track objects.
This commit is contained in:
@@ -307,6 +307,8 @@ void PhysicalObject::init()
|
||||
}
|
||||
case MP_EXACT:
|
||||
{
|
||||
m_graphical_offset = Vec3(0,0,0);
|
||||
extend.setY(0);
|
||||
TriangleMesh* triangle_mesh = new TriangleMesh();
|
||||
|
||||
// In case of readonly materials we have to get the material from
|
||||
@@ -471,7 +473,8 @@ void PhysicalObject::init()
|
||||
}
|
||||
|
||||
World::getWorld()->getPhysics()->addBody(m_body);
|
||||
|
||||
if(m_triangle_mesh)
|
||||
m_triangle_mesh->setBody(m_body);
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -504,6 +507,40 @@ void PhysicalObject::update(float dt)
|
||||
return;
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Does a raycast against this physical object. The physical object must
|
||||
* have an 'exact' shape, i.e. be a triangle mesh (for other physical objects
|
||||
* no material information would be available).
|
||||
* \param from/to The from and to position for the raycast.
|
||||
* \param xyz The position in world where the ray hit.
|
||||
* \param material The material of the mesh that was hit.
|
||||
* \param normal The intrapolated normal at that position.
|
||||
* \param interpolate_normal If true, the returned normal is the interpolated
|
||||
* based on the three normals of the triangle and the location of the
|
||||
* hit point (which is more compute intensive, but results in much
|
||||
* smoother results).
|
||||
* \return True if a triangle was hit, false otherwise (and no output
|
||||
* variable will be set.
|
||||
*/
|
||||
bool PhysicalObject::castRay(const btVector3 &from, const btVector3 &to,
|
||||
btVector3 *hit_point, const Material **material,
|
||||
btVector3 *normal, bool interpolate_normal) const
|
||||
{
|
||||
if(m_body_type!=MP_EXACT)
|
||||
{
|
||||
Log::warn("PhysicalObject", "Can only raycast against 'exact' meshes.");
|
||||
return false;
|
||||
}
|
||||
Vec3 dxyz(m_init_xyz);
|
||||
//bool result = m_triangle_mesh->castRay(from-dxyz, to-dxyz, hit_point,
|
||||
bool result = m_triangle_mesh->castRay(from, to, hit_point,
|
||||
material, normal,
|
||||
interpolate_normal);
|
||||
// if(result)
|
||||
// *hit_point += (btVector3)dxyz;
|
||||
return result;
|
||||
} // castRay
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void PhysicalObject::reset()
|
||||
{
|
||||
|
||||
@@ -159,6 +159,11 @@ public:
|
||||
void move (const Vec3& xyz, const core::vector3df& hpr);
|
||||
void hit (const Material *m, const Vec3 &normal);
|
||||
bool isSoccerBall () const;
|
||||
bool castRay(const btVector3 &from,
|
||||
const btVector3 &to, btVector3 *hit_point,
|
||||
const Material **material, btVector3 *normal,
|
||||
bool interpolate_normal) const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the rigid body of this physical object. */
|
||||
btRigidBody *getBody () { return m_body; }
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
TriangleMesh::TriangleMesh() : m_mesh()
|
||||
{
|
||||
m_body = NULL;
|
||||
m_free_body = true;
|
||||
m_motion_state = NULL;
|
||||
// FIXME: on VS in release mode this statement actually overwrites
|
||||
// part of the data of m_mesh, causing a crash later. Debugging
|
||||
@@ -200,7 +201,8 @@ void TriangleMesh::createPhysicalBody(btCollisionObject::CollisionFlags flags,
|
||||
*/
|
||||
void TriangleMesh::removeAll()
|
||||
{
|
||||
if(m_body)
|
||||
// Don't free the physical body if it was created outside this object.
|
||||
if(m_body && m_free_body)
|
||||
{
|
||||
World::getWorld()->getPhysics()->removeBody(m_body);
|
||||
delete m_body;
|
||||
@@ -301,6 +303,8 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
|
||||
|
||||
btTransform world_trans;
|
||||
world_trans.setIdentity();
|
||||
if(m_body)
|
||||
world_trans = m_body->getWorldTransform();
|
||||
|
||||
btCollisionWorld::ClosestRayResultCallback result(from, to);
|
||||
|
||||
@@ -334,8 +338,8 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
|
||||
// If this is a rigid body, m_collision_object is NULL, and the
|
||||
// rigid body is the actual collision object.
|
||||
btCollisionWorld::rayTestSingle(trans_from, trans_to,
|
||||
m_collision_object ? m_collision_object
|
||||
: m_body,
|
||||
// m_body ? m_body : m_collision_object,
|
||||
m_collision_object ? m_collision_object : m_body,
|
||||
m_collision_shape, world_trans,
|
||||
ray_callback);
|
||||
// Get the index of the triangle hit
|
||||
|
||||
@@ -37,6 +37,9 @@ private:
|
||||
UserPointer m_user_pointer;
|
||||
std::vector<const Material*> m_triangleIndex2Material;
|
||||
btRigidBody *m_body;
|
||||
/** Keep track if the physical body was created here or not. */
|
||||
bool m_free_body;
|
||||
|
||||
btCollisionObject *m_collision_object;
|
||||
btTriangleMesh m_mesh;
|
||||
btVector3 dummy1, dummy2;
|
||||
@@ -60,6 +63,13 @@ public:
|
||||
btVector3 getInterpolatedNormal(unsigned int index,
|
||||
const btVector3 &position) const;
|
||||
// ------------------------------------------------------------------------
|
||||
void setBody(btRigidBody *body)
|
||||
{
|
||||
assert(!m_body);
|
||||
m_free_body = false;
|
||||
m_body = body;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
const Material* getMaterial(int n) const
|
||||
{return m_triangleIndex2Material[n];}
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -18,14 +18,16 @@
|
||||
|
||||
#include "tracks/terrain_info.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "modes/world.hpp"
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/** Constructor to initialise terrain data.
|
||||
*/
|
||||
TerrainInfo::TerrainInfo()
|
||||
@@ -59,6 +61,10 @@ void TerrainInfo::update(const Vec3 &from)
|
||||
const TriangleMesh &tm = World::getWorld()->getTrack()->getTriangleMesh();
|
||||
tm.castRay(from, to, &m_hit_point, &m_material, &m_normal,
|
||||
/*interpolate*/false);
|
||||
// Now also raycast against all track objects (that are driveable).
|
||||
World::getWorld()->getTrack()->getTrackObjectManager()
|
||||
->castRay(from, to, &m_hit_point, &m_material,
|
||||
&m_normal, /*interpolate*/false);
|
||||
} // update
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Update the terrain information based on the latest position.
|
||||
@@ -74,6 +80,10 @@ void TerrainInfo::update(const btTransform &trans, const Vec3 &offset)
|
||||
const TriangleMesh &tm = World::getWorld()->getTrack()->getTriangleMesh();
|
||||
tm.castRay(from, to, &m_hit_point, &m_material, &m_normal,
|
||||
/*interpolate*/true);
|
||||
// Now also raycast against all track objects (that are driveable).
|
||||
World::getWorld()->getTrack()->getTrackObjectManager()
|
||||
->castRay(from, to, &m_hit_point, &m_material,
|
||||
&m_normal, /*interpolate*/true);
|
||||
} // update
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -2389,7 +2389,7 @@ std::vector< std::vector<float> > Track::buildHeightMap()
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
} // buildHeightMap
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the rotation of the sun. */
|
||||
|
||||
@@ -42,7 +42,7 @@ TrackObject::TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
ModelDefinitionLoader& model_def_loader)
|
||||
{
|
||||
init(xml_node, parent, model_def_loader);
|
||||
}
|
||||
} // TrackObject
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/**
|
||||
@@ -56,29 +56,33 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||
bool is_dynamic,
|
||||
const PhysicalObject::Settings* physics_settings)
|
||||
{
|
||||
m_init_xyz = xyz;
|
||||
m_init_hpr = hpr;
|
||||
m_init_scale = scale;
|
||||
m_enabled = true;
|
||||
m_presentation = NULL;
|
||||
m_animator = NULL;
|
||||
m_init_xyz = xyz;
|
||||
m_init_hpr = hpr;
|
||||
m_init_scale = scale;
|
||||
m_enabled = true;
|
||||
m_presentation = NULL;
|
||||
m_animator = NULL;
|
||||
m_physical_object = NULL;
|
||||
m_interaction = interaction;
|
||||
|
||||
m_presentation = presentation;
|
||||
m_interaction = interaction;
|
||||
m_presentation = presentation;
|
||||
|
||||
if (m_interaction != "ghost" && m_interaction != "none" &&
|
||||
physics_settings )
|
||||
{
|
||||
m_physical_object = new PhysicalObject(is_dynamic,
|
||||
*physics_settings,
|
||||
this);
|
||||
*physics_settings,
|
||||
this);
|
||||
}
|
||||
|
||||
reset();
|
||||
} // TrackObject
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises the track object based on the specified XML data.
|
||||
* \param xml_node The XML data.
|
||||
* \param parent The parent scene node.
|
||||
* \param model_def_loader Used to load level-of-detail nodes.
|
||||
*/
|
||||
void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
ModelDefinitionLoader& model_def_loader)
|
||||
{
|
||||
@@ -100,6 +104,9 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
xml_node.get("interaction", &m_interaction);
|
||||
xml_node.get("lod_group", &m_lod_group);
|
||||
|
||||
m_is_driveable = false;
|
||||
xml_node.get("driveable", &m_is_driveable);
|
||||
|
||||
bool lod_instance = false;
|
||||
xml_node.get("lod_instance", &lod_instance);
|
||||
|
||||
@@ -252,14 +259,42 @@ void TrackObject::setEnable(bool mode)
|
||||
// ----------------------------------------------------------------------------
|
||||
void TrackObject::update(float dt)
|
||||
{
|
||||
if (m_presentation != NULL) m_presentation->update(dt);
|
||||
if (m_presentation) m_presentation->update(dt);
|
||||
|
||||
if (m_physical_object != NULL) m_physical_object->update(dt);
|
||||
if (m_physical_object) m_physical_object->update(dt);
|
||||
|
||||
if (m_animator != NULL) m_animator->update(dt);
|
||||
if (m_animator) m_animator->update(dt);
|
||||
} // update
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Does a raycast against the track object. The object must have a physical
|
||||
* object.
|
||||
* \param from/to The from and to position for the raycast.
|
||||
* \param xyz The position in world where the ray hit.
|
||||
* \param material The material of the mesh that was hit.
|
||||
* \param normal The intrapolated normal at that position.
|
||||
* \param interpolate_normal If true, the returned normal is the interpolated
|
||||
* based on the three normals of the triangle and the location of the
|
||||
* hit point (which is more compute intensive, but results in much
|
||||
* smoother results).
|
||||
* \return True if a triangle was hit, false otherwise (and no output
|
||||
* variable will be set.
|
||||
*/
|
||||
bool TrackObject::castRay(const btVector3 &from,
|
||||
const btVector3 &to, btVector3 *hit_point,
|
||||
const Material **material, btVector3 *normal,
|
||||
bool interpolate_normal) const
|
||||
{
|
||||
if(!m_physical_object)
|
||||
{
|
||||
Log::warn("TrackObject", "Can't raycast on non-physical object.");
|
||||
return false;
|
||||
}
|
||||
return m_physical_object->castRay(from, to, hit_point, material, normal,
|
||||
interpolate_normal);
|
||||
} // castRay
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void TrackObject::move(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||
|
||||
@@ -75,7 +75,10 @@ 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;
|
||||
@@ -96,46 +99,61 @@ public:
|
||||
const PhysicalObject::Settings* physicsSettings);
|
||||
virtual ~TrackObject();
|
||||
virtual void update(float dt);
|
||||
virtual void reset();
|
||||
/** To finish object constructions. Called after the track model
|
||||
* is ready. */
|
||||
virtual void init() {};
|
||||
/** Called when an explosion happens. As a default does nothing, will
|
||||
* e.g. be overwritten by physical objects etc. */
|
||||
virtual void handleExplosion(const Vec3& pos, bool directHit) {};
|
||||
void setEnable(bool mode);
|
||||
|
||||
const std::string& getLodGroup() const { return m_lod_group; }
|
||||
|
||||
const std::string& getType() const { return m_type; }
|
||||
|
||||
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; }
|
||||
|
||||
const core::vector3df getInitXYZ() const { return m_init_xyz; }
|
||||
const core::vector3df getInitRotation() const { return m_init_hpr; }
|
||||
const core::vector3df getInitScale() const { return m_init_scale; }
|
||||
|
||||
void move(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||
const core::vector3df& scale, bool updateRigidBody);
|
||||
|
||||
template<typename T>
|
||||
T* getPresentation() { return dynamic_cast<T*>(m_presentation); }
|
||||
|
||||
template<typename T>
|
||||
const T* getPresentation() const { return dynamic_cast<T*>(m_presentation); }
|
||||
|
||||
ThreeDAnimation* getAnimator() { return m_animator; }
|
||||
const ThreeDAnimation* getAnimator() const { return m_animator; }
|
||||
|
||||
virtual void reset();
|
||||
void setEnable(bool mode);
|
||||
const core::vector3df& getPosition() const;
|
||||
const core::vector3df getAbsolutePosition() const;
|
||||
const core::vector3df& getRotation() const;
|
||||
const core::vector3df& getScale() const;
|
||||
bool castRay(const btVector3 &from,
|
||||
const btVector3 &to, btVector3 *hit_point,
|
||||
const Material **material, btVector3 *normal,
|
||||
bool interpolate_normal) const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** To finish object constructions. Called after the track model
|
||||
* is ready. */
|
||||
virtual void init() {};
|
||||
// ------------------------------------------------------------------------
|
||||
/** Called when an explosion happens. As a default does nothing, will
|
||||
* e.g. be overwritten by physical objects etc. */
|
||||
virtual void handleExplosion(const Vec3& pos, bool directHit) {};
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getLodGroup() const { return m_lod_group; }
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getType() const { return m_type; }
|
||||
// ------------------------------------------------------------------------
|
||||
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; }
|
||||
// ------------------------------------------------------------------------
|
||||
const core::vector3df getInitXYZ() const { return m_init_xyz; }
|
||||
// ------------------------------------------------------------------------
|
||||
const core::vector3df getInitRotation() const { return m_init_hpr; }
|
||||
// ------------------------------------------------------------------------
|
||||
const core::vector3df getInitScale() const { return m_init_scale; }
|
||||
// ------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
T* getPresentation() { return dynamic_cast<T*>(m_presentation); }
|
||||
// ------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
const T* getPresentation() const { return dynamic_cast<T*>(m_presentation); }
|
||||
// ------------------------------------------------------------------------
|
||||
ThreeDAnimation* getAnimator() { return m_animator; }
|
||||
// ------------------------------------------------------------------------
|
||||
const ThreeDAnimation* getAnimator() const { return m_animator; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if a kart can drive on this object. */
|
||||
bool isDriveable() const { return m_is_driveable; }
|
||||
|
||||
LEAK_CHECK()
|
||||
}; // TrackObject
|
||||
|
||||
@@ -50,11 +50,15 @@ TrackObjectManager::~TrackObjectManager()
|
||||
* in a separate section that's read before everything and remove all this
|
||||
* crap
|
||||
*/
|
||||
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader)
|
||||
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
ModelDefinitionLoader& model_def_loader)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_all_objects.push_back(new TrackObject(xml_node, parent, model_def_loader));
|
||||
TrackObject *obj = new TrackObject(xml_node, parent, model_def_loader);
|
||||
m_all_objects.push_back(obj);
|
||||
if(obj->isDriveable())
|
||||
m_driveable_objects.push_back(obj);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@@ -120,6 +124,40 @@ void TrackObjectManager::update(float dt)
|
||||
}
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void TrackObjectManager::castRay(const btVector3 &from,
|
||||
const btVector3 &to, btVector3 *hit_point,
|
||||
const Material **material,
|
||||
btVector3 *normal,
|
||||
bool interpolate_normal) const
|
||||
{
|
||||
float distance = 9999.9f;
|
||||
// If there was a hit already, compute the current distance
|
||||
if(*material)
|
||||
{
|
||||
distance = hit_point->distance(from);
|
||||
}
|
||||
const TrackObject* curr;
|
||||
for_in (curr, m_driveable_objects)
|
||||
{
|
||||
btVector3 new_hit_point;
|
||||
const Material *new_material;
|
||||
btVector3 new_normal;
|
||||
if(curr->castRay(from, to, &new_hit_point, &new_material, &new_normal,
|
||||
interpolate_normal))
|
||||
{
|
||||
float new_distance = new_hit_point.distance(from);
|
||||
if (new_distance < distance)
|
||||
{
|
||||
*material = new_material;
|
||||
*hit_point = new_hit_point;
|
||||
*normal = new_normal;
|
||||
distance = new_distance;
|
||||
} // if new_distance < distance
|
||||
} // if hit
|
||||
} // for all track objects.
|
||||
} // castRay
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Enables or disables fog for a given scene node.
|
||||
* \param node The node to adjust.
|
||||
|
||||
@@ -44,17 +44,27 @@ protected:
|
||||
* eye candy (to reduce work for physics), ...
|
||||
*/
|
||||
enum TrackObjectType {TO_PHYSICAL, TO_GRAPHICAL};
|
||||
|
||||
/** The list of all track objects. */
|
||||
PtrVector<TrackObject> m_all_objects;
|
||||
|
||||
/** A second list which holds all objects that karts can drive on. */
|
||||
PtrVector<TrackObject, REF> m_driveable_objects;
|
||||
|
||||
public:
|
||||
TrackObjectManager();
|
||||
~TrackObjectManager();
|
||||
void add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader);
|
||||
void reset();
|
||||
void init();
|
||||
void add(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
ModelDefinitionLoader& model_def_loader);
|
||||
void update(float dt);
|
||||
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp,
|
||||
bool secondary_hits=true);
|
||||
void reset();
|
||||
void init();
|
||||
void castRay(const btVector3 &from,
|
||||
const btVector3 &to, btVector3 *hit_point,
|
||||
const Material **material, btVector3 *normal = NULL,
|
||||
bool interpolate_normal = false) const;
|
||||
|
||||
/** Enable or disable fog on objects */
|
||||
void enableFog(bool enable);
|
||||
|
||||
Reference in New Issue
Block a user