1) Made TrackObject use an ISceneNode instead of an IAnimatedMeshSceneNode,
allowing us to use the same base class for billboard. 2) Fixed billboard implementation: billboards are now properly removed, and can also be IPO animated. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@6861 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -32,9 +32,9 @@ AnimationManager::AnimationManager(const Track &track, const XMLNode &node)
|
||||
const XMLNode *anim_node = node.getNode(i);
|
||||
std::string type = anim_node->getName();
|
||||
if(type=="anim_billboard")
|
||||
m_all_animations.push_back(new BillboardAnimation(track, *anim_node));
|
||||
m_all_animations.push_back(new BillboardAnimation(*anim_node));
|
||||
else if(type=="animations-IPO")
|
||||
m_all_animations.push_back(new ThreeDAnimation(track, *anim_node));
|
||||
m_all_animations.push_back(new ThreeDAnimation(*anim_node));
|
||||
else
|
||||
fprintf(stderr, "Unknown animation type '%s' - ignored.\n",
|
||||
type.c_str());
|
||||
|
||||
@@ -18,14 +18,30 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "animations/billboard_animation.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
|
||||
class XMLNode;
|
||||
|
||||
/** A 2d billboard animation. */
|
||||
BillboardAnimation::BillboardAnimation(const Track &track_name,
|
||||
const XMLNode &node)
|
||||
: AnimationBase(node)
|
||||
BillboardAnimation::BillboardAnimation(const XMLNode &xml_node)
|
||||
: AnimationBase(xml_node)
|
||||
{
|
||||
std::string texture_name;
|
||||
float width, height;
|
||||
|
||||
xml_node.get("texture", &texture_name);
|
||||
xml_node.get("width", &width );
|
||||
xml_node.get("height", &height );
|
||||
core::vector3df xyz;
|
||||
xml_node.getXYZ(&xyz);
|
||||
video::ITexture *texture =
|
||||
irr_driver->getTexture(file_manager->getTextureFile(texture_name));
|
||||
m_node = irr_driver->addBillboard(core::dimension2df(width, height),
|
||||
texture);
|
||||
m_node-> setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL );
|
||||
|
||||
m_node->setPosition(xyz);
|
||||
} // BillboardAnimation
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -33,10 +49,11 @@ BillboardAnimation::BillboardAnimation(const Track &track_name,
|
||||
* \param dt Time since last call. */
|
||||
void BillboardAnimation::update(float dt)
|
||||
{
|
||||
// FIXME: not implemented yet.
|
||||
core::vector3df xyz(0, 0, 0);
|
||||
core::vector3df hpr(0, 0, 0);
|
||||
core::vector3df scale(1,1,1);
|
||||
AnimationBase::update(dt, &xyz, &hpr, &scale);
|
||||
|
||||
m_node->setPosition(xyz);
|
||||
m_node->setScale(xyz);
|
||||
// Setting rotation doesn't make sense
|
||||
} // update
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "irrlicht.h"
|
||||
using namespace irr;
|
||||
|
||||
#include "animations/animation_base.hpp"
|
||||
|
||||
class Track;
|
||||
@@ -33,11 +36,9 @@ class XMLNode;
|
||||
*/
|
||||
class BillboardAnimation : public AnimationBase
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
BillboardAnimation(const Track &track, const XMLNode &node);
|
||||
virtual ~BillboardAnimation(){}
|
||||
BillboardAnimation(const XMLNode &node);
|
||||
virtual ~BillboardAnimation() {};
|
||||
virtual void update(float dt);
|
||||
|
||||
}; // BillboardAnimation
|
||||
|
||||
@@ -29,20 +29,19 @@
|
||||
#include "physics/physics.hpp"
|
||||
#include "physics/kart_motion_state.hpp"
|
||||
#include "tracks/bezier_curve.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
ThreeDAnimation::ThreeDAnimation(const Track &track,
|
||||
const XMLNode &node)
|
||||
ThreeDAnimation::ThreeDAnimation(const XMLNode &node)
|
||||
: AnimationBase(node)
|
||||
{
|
||||
/** Save the initial position and rotation in the base animation object. */
|
||||
setInitialTransform(m_animated_node->getPosition(), m_animated_node->getRotation());
|
||||
setInitialTransform(AnimationBase::m_node->getPosition(),
|
||||
AnimationBase::m_node->getRotation() );
|
||||
|
||||
m_body = NULL;
|
||||
m_motion_state = NULL;
|
||||
m_collision_shape = NULL;
|
||||
m_hpr = AnimationBase::m_animated_node->getRotation();
|
||||
m_hpr = AnimationBase::m_node->getRotation();
|
||||
std::string shape;
|
||||
node.get("shape", &shape);
|
||||
if(shape!="")
|
||||
@@ -58,7 +57,9 @@ void ThreeDAnimation::createPhysicsBody(const std::string &shape)
|
||||
// 1. Determine size of the object
|
||||
// -------------------------------
|
||||
Vec3 min, max;
|
||||
MeshTools::minMax3D(m_animated_mesh, &min, &max);
|
||||
scene::IAnimatedMesh *mesh =
|
||||
((scene::IAnimatedMeshSceneNode*)m_node)->getMesh();
|
||||
MeshTools::minMax3D(mesh, &min, &max);
|
||||
Vec3 extend = max-min;
|
||||
if(shape=="box")
|
||||
{
|
||||
@@ -87,9 +88,9 @@ void ThreeDAnimation::createPhysicsBody(const std::string &shape)
|
||||
fprintf(stderr, "Shape '%s' is not supported, ignored.\n", shape.c_str());
|
||||
return;
|
||||
}
|
||||
const core::vector3df &hpr=m_animated_node->getRotation()*DEGREE_TO_RAD;
|
||||
const core::vector3df &hpr=m_node->getRotation()*DEGREE_TO_RAD;
|
||||
btQuaternion q(hpr.X, hpr.Y, hpr.Z);
|
||||
const core::vector3df &xyz=m_animated_node->getPosition();
|
||||
const core::vector3df &xyz=m_node->getPosition();
|
||||
Vec3 p(xyz);
|
||||
btTransform trans(q,p);
|
||||
m_motion_state = new KartMotionState(trans);
|
||||
@@ -123,11 +124,11 @@ ThreeDAnimation::~ThreeDAnimation()
|
||||
*/
|
||||
void ThreeDAnimation::update(float dt)
|
||||
{
|
||||
core::vector3df xyz = m_animated_node->getPosition();
|
||||
core::vector3df scale = m_animated_node->getScale();
|
||||
core::vector3df xyz = m_node->getPosition();
|
||||
core::vector3df scale = m_node->getScale();
|
||||
AnimationBase::update(dt, &xyz, &m_hpr, &scale); //updates all IPOs
|
||||
m_animated_node->setPosition(xyz);
|
||||
m_animated_node->setScale(scale);
|
||||
m_node->setPosition(xyz);
|
||||
m_node->setScale(scale);
|
||||
// Note that the rotation order of irrlicht is different from the one
|
||||
// in blender. So in order to reproduce the blender IPO rotations
|
||||
// correctly, we have to get the rotations around each axis and combine
|
||||
@@ -142,7 +143,7 @@ void ThreeDAnimation::update(float dt)
|
||||
mz.setRotationDegrees(core::vector3df(0, 0, m_hpr.Z));
|
||||
m = my*mz*mx;
|
||||
core::vector3df hpr = m.getRotationDegrees();
|
||||
m_animated_node->setRotation(hpr);
|
||||
m_node->setRotation(hpr);
|
||||
|
||||
// Now update the position of the bullet body if there is one:
|
||||
if(m_body)
|
||||
|
||||
@@ -31,7 +31,6 @@ using namespace irr;
|
||||
#include "physics/user_pointer.hpp"
|
||||
|
||||
class BezierCurve;
|
||||
class Track;
|
||||
class XMLNode;
|
||||
|
||||
/** \brief A virtual base class for all animations.
|
||||
@@ -60,7 +59,7 @@ private:
|
||||
void createPhysicsBody(const std::string &shape);
|
||||
|
||||
public:
|
||||
ThreeDAnimation(const Track &track, const XMLNode &node);
|
||||
ThreeDAnimation(const XMLNode &node);
|
||||
virtual ~ThreeDAnimation();
|
||||
virtual void update(float dt);
|
||||
|
||||
|
||||
@@ -67,7 +67,11 @@ float MainLoop::getLimitedDt()
|
||||
// don't allow the game to run slower than a certain amount.
|
||||
// when the computer can't keep it up, slow down the shown time instead
|
||||
static const float max_elapsed_time = 3.0f*1.0f/60.0f*1000.0f; /* time 3 internal substeps take */
|
||||
if(dt > max_elapsed_time) dt=max_elapsed_time;
|
||||
if(dt > max_elapsed_time)
|
||||
{
|
||||
printf("slowdown: max elapsed %f dt %f\n", max_elapsed_time, dt);
|
||||
dt=max_elapsed_time;
|
||||
}
|
||||
|
||||
// Throttle fps if more than maximum, which can reduce
|
||||
// the noise the fan on a graphics card makes.
|
||||
|
||||
@@ -78,12 +78,12 @@ PhysicalObject::~PhysicalObject()
|
||||
*/
|
||||
void PhysicalObject::init()
|
||||
{
|
||||
assert(m_animated_mesh);
|
||||
|
||||
// 1. Determine size of the object
|
||||
// -------------------------------
|
||||
Vec3 min, max;
|
||||
MeshTools::minMax3D(m_animated_mesh, &min, &max);
|
||||
scene::IAnimatedMesh *mesh
|
||||
= ((scene::IAnimatedMeshSceneNode*)m_node)->getMesh();
|
||||
MeshTools::minMax3D(mesh, &min, &max);
|
||||
Vec3 extend = max-min;
|
||||
// Adjust the mesth of the graphical object so that its center is where it
|
||||
// is in bullet (usually at (0,0,0)). It can be changed in the case clause
|
||||
@@ -133,7 +133,7 @@ void PhysicalObject::init()
|
||||
irr_driver->getSceneManager()->getMeshManipulator();
|
||||
core::matrix4 transform(core::matrix4::EM4CONST_IDENTITY); //
|
||||
transform.setTranslation(offset_from_center.toIrrVector());
|
||||
mesh_manipulator->transformMesh(m_animated_mesh, transform);
|
||||
mesh_manipulator->transformMesh(mesh, transform);
|
||||
|
||||
// 2. Create the rigid object
|
||||
// --------------------------
|
||||
@@ -167,10 +167,10 @@ void PhysicalObject::update(float dt)
|
||||
m_body->setAngularVelocity(btVector3(0,0,0));
|
||||
xyz = Vec3(m_init_pos.getOrigin());
|
||||
}
|
||||
m_animated_node->setPosition(xyz.toIrrVector());
|
||||
m_node->setPosition(xyz.toIrrVector());
|
||||
Vec3 hpr;
|
||||
hpr.setHPR(t.getRotation());
|
||||
m_animated_node->setRotation(hpr.toIrrHPR());
|
||||
m_node->setRotation(hpr.toIrrHPR());
|
||||
return;
|
||||
} // update
|
||||
|
||||
|
||||
@@ -403,6 +403,7 @@ void Track::convertTrackToBullet(scene::ISceneNode *node)
|
||||
// overwrite the elements on the diagonal, making any rotation incorrect.
|
||||
mat_scale.setScale(scale);
|
||||
mat *= mat_scale;
|
||||
printf("track mbc for %s %d\n", node->getName(), mesh->getMeshBufferCount());
|
||||
for(unsigned int i=0; i<mesh->getMeshBufferCount(); i++) {
|
||||
scene::IMeshBuffer *mb = mesh->getMeshBuffer(i);
|
||||
// FIXME: take translation/rotation into account
|
||||
@@ -778,7 +779,7 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
|
||||
if(name=="track" || name=="default-start") continue;
|
||||
if(name=="object")
|
||||
{
|
||||
m_track_object_manager->add(*node, *this);
|
||||
m_track_object_manager->add(*node);
|
||||
}
|
||||
else if(name=="water")
|
||||
{
|
||||
@@ -834,23 +835,6 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
|
||||
{
|
||||
m_check_manager = new CheckManager(*node, this);
|
||||
}
|
||||
else if (name=="billboard")
|
||||
{
|
||||
std::vector<float> billboard_size;
|
||||
std::vector<float> billboard_origin;
|
||||
std::string path;
|
||||
node->get("texture", &path);
|
||||
node->get("size", &billboard_size);
|
||||
node->get("origin", &billboard_origin);
|
||||
|
||||
video::ITexture* billboard_texture_load;
|
||||
|
||||
billboard_texture_load = irr_driver->getTexture(path);
|
||||
scene::ISceneNode* node3d;
|
||||
node3d = irr_driver->addBillboard(core::dimension2d< f32 >( billboard_size[0], billboard_size[1] ), billboard_texture_load);
|
||||
node3d -> setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL );
|
||||
node3d -> setPosition(core::vector3df( billboard_origin[0], billboard_origin[2], billboard_origin[1] ));
|
||||
}
|
||||
else if (name=="particle-emitter")
|
||||
{
|
||||
// based on http://irrlicht.sourceforge.net/tut008.html
|
||||
|
||||
@@ -35,68 +35,71 @@
|
||||
*/
|
||||
TrackObject::TrackObject(const XMLNode &xml_node)
|
||||
{
|
||||
|
||||
std::string model_name;
|
||||
xml_node.get("model", &model_name);
|
||||
std::string full_path = World::getWorld()->getTrack()->getTrackFile(model_name);
|
||||
m_animated_mesh = irr_driver->getAnimatedMesh(full_path);
|
||||
if(!m_animated_mesh)
|
||||
{
|
||||
// If the model isn't found in the track directory, look
|
||||
// in STK's model directory.
|
||||
full_path = file_manager->getModelFile(model_name);
|
||||
m_animated_mesh = irr_driver->getAnimatedMesh(full_path);
|
||||
if(!m_animated_mesh)
|
||||
{
|
||||
fprintf(stderr, "Warning: '%s' in '%s' not found and is ignored.\n",
|
||||
xml_node.getName().c_str(), model_name.c_str());
|
||||
return;
|
||||
} // if(!m_animated_mesh)
|
||||
}
|
||||
m_animated_node = irr_driver->addAnimatedMesh(m_animated_mesh);
|
||||
#ifdef DEBUG
|
||||
std::string debug_name = model_name+" (track-object)";
|
||||
m_animated_node->setName(debug_name.c_str());
|
||||
#endif
|
||||
|
||||
// Get the information from the xml node.
|
||||
m_enabled = true;
|
||||
xml_node.get("enabled", &m_enabled);
|
||||
|
||||
m_is_looped = false;
|
||||
xml_node.get("looped", &m_is_looped);
|
||||
|
||||
m_frame_start = m_animated_node->getStartFrame();
|
||||
xml_node.get("frame-start", &m_frame_start);
|
||||
|
||||
m_frame_end = m_animated_node->getEndFrame();
|
||||
xml_node.get("frame-end", &m_frame_end);
|
||||
|
||||
if(!m_enabled)
|
||||
m_animated_node->setVisible(false);
|
||||
|
||||
m_init_xyz = core::vector3df(0,0,0);
|
||||
int result = xml_node.get("xyz", &m_init_xyz);
|
||||
m_init_hpr = core::vector3df(0,0,0);
|
||||
result = xml_node.get("hpr", &m_init_hpr);
|
||||
m_init_scale = core::vector3df(1,1,1);
|
||||
result = xml_node.get("scale", &m_init_scale);
|
||||
if(!XMLNode::hasP(result) ||
|
||||
!XMLNode::hasR(result)) // Needs perhaps pitch and roll
|
||||
m_enabled = true;
|
||||
m_is_looped = false;
|
||||
|
||||
xml_node.get("xyz", &m_init_xyz );
|
||||
xml_node.get("hpr", &m_init_hpr );
|
||||
xml_node.get("scale", &m_init_scale);
|
||||
xml_node.get("enabled", &m_enabled );
|
||||
xml_node.get("looped", &m_is_looped );
|
||||
std::string model_name;
|
||||
xml_node.get("model", &model_name );
|
||||
|
||||
// Some animated objects (billboards) don't use this scene node
|
||||
if(model_name=="")
|
||||
{
|
||||
m_node = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string full_path = World::getWorld()->getTrack()->getTrackFile(model_name);
|
||||
scene::IAnimatedMesh *mesh = irr_driver->getAnimatedMesh(full_path);
|
||||
if(!mesh)
|
||||
{
|
||||
// If the model isn't found in the track directory, look
|
||||
// in STK's model directory.
|
||||
full_path = file_manager->getModelFile(model_name);
|
||||
mesh = irr_driver->getAnimatedMesh(full_path);
|
||||
if(!mesh)
|
||||
{
|
||||
fprintf(stderr, "Warning: '%s' in '%s' not found and is ignored.\n",
|
||||
xml_node.getName().c_str(), model_name.c_str());
|
||||
return;
|
||||
} // if(!mesh)
|
||||
}
|
||||
|
||||
scene::IAnimatedMeshSceneNode *node=irr_driver->addAnimatedMesh(mesh);
|
||||
m_node = node;
|
||||
#ifdef DEBUG
|
||||
std::string debug_name = model_name+" (track-object)";
|
||||
m_node->setName(debug_name.c_str());
|
||||
#endif
|
||||
m_frame_start = node->getStartFrame();
|
||||
xml_node.get("frame-start", &m_frame_start);
|
||||
|
||||
m_frame_end = node->getEndFrame();
|
||||
xml_node.get("frame-end", &m_frame_end);
|
||||
|
||||
if(!m_enabled)
|
||||
m_node->setVisible(false);
|
||||
|
||||
m_node->setPosition(m_init_xyz);
|
||||
m_node->setRotation(m_init_hpr);
|
||||
m_node->setScale(m_init_scale);
|
||||
m_node->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
}
|
||||
m_animated_node->setPosition(m_init_xyz);
|
||||
m_animated_node->setRotation(m_init_hpr);
|
||||
m_animated_node->setScale(m_init_scale);
|
||||
m_animated_node->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
reset();
|
||||
} // TrackObject
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
TrackObject::~TrackObject()
|
||||
{
|
||||
irr_driver->removeNode(m_animated_node);
|
||||
irr_driver->removeMesh(m_animated_mesh);
|
||||
if(m_node)
|
||||
irr_driver->removeNode(m_node);
|
||||
} // ~TrackObject
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -104,14 +107,21 @@ TrackObject::~TrackObject()
|
||||
*/
|
||||
void TrackObject::reset()
|
||||
{
|
||||
m_animated_node->setPosition(m_init_xyz);
|
||||
m_animated_node->setRotation(m_init_hpr);
|
||||
m_animated_node->setScale(m_init_scale);
|
||||
m_animated_node->setLoopMode(m_is_looped);
|
||||
|
||||
if(m_is_looped)
|
||||
if(!m_node) return;
|
||||
if(m_node->getType()==scene::ESNT_ANIMATED_MESH)
|
||||
{
|
||||
m_animated_node->setFrameLoop(m_frame_start, m_frame_end);
|
||||
scene::IAnimatedMeshSceneNode *a_node =
|
||||
(scene::IAnimatedMeshSceneNode*)m_node;
|
||||
|
||||
a_node->setPosition(m_init_xyz);
|
||||
a_node->setRotation(m_init_hpr);
|
||||
a_node->setScale(m_init_scale);
|
||||
a_node->setLoopMode(m_is_looped);
|
||||
|
||||
if(m_is_looped)
|
||||
{
|
||||
a_node->setFrameLoop(m_frame_start, m_frame_end);
|
||||
}
|
||||
}
|
||||
} // reset
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -122,7 +132,8 @@ void TrackObject::reset()
|
||||
void TrackObject::setEnable(bool mode)
|
||||
{
|
||||
m_enabled = mode;
|
||||
m_animated_node->setVisible(m_enabled);
|
||||
if(m_node)
|
||||
m_node->setVisible(m_enabled);
|
||||
} // setEnable
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This function is called from irrlicht when a (non-looped) animation ends.
|
||||
|
||||
@@ -58,11 +58,8 @@ private:
|
||||
virtual void OnAnimationEnd(scene::IAnimatedMeshSceneNode* node);
|
||||
|
||||
protected:
|
||||
/** The irrlicht mesh for this object. */
|
||||
scene::IAnimatedMesh *m_animated_mesh;
|
||||
|
||||
/** The irrlicht scene node this object is attached to. */
|
||||
scene::IAnimatedMeshSceneNode *m_animated_node;
|
||||
scene::ISceneNode *m_node;
|
||||
|
||||
/** The initial XYZ position of the object. */
|
||||
core::vector3df m_init_xyz;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "animations/billboard_animation.hpp"
|
||||
#include "animations/three_d_animation.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "physics/physical_object.hpp"
|
||||
@@ -42,7 +43,7 @@ TrackObjectManager::~TrackObjectManager()
|
||||
/** Adds an object to the track object manager. The type to add is specified
|
||||
* in the xml_node.
|
||||
*/
|
||||
void TrackObjectManager::add(const XMLNode &xml_node, const Track &track)
|
||||
void TrackObjectManager::add(const XMLNode &xml_node)
|
||||
{
|
||||
std::string type;
|
||||
xml_node.get("type", &type);
|
||||
@@ -52,11 +53,16 @@ void TrackObjectManager::add(const XMLNode &xml_node, const Track &track)
|
||||
}
|
||||
else if(type=="animation")
|
||||
{
|
||||
m_all_objects.push_back(new ThreeDAnimation(track, xml_node));
|
||||
m_all_objects.push_back(new ThreeDAnimation(xml_node));
|
||||
}
|
||||
else if(type=="billboard")
|
||||
{
|
||||
m_all_objects.push_back(new BillboardAnimation(xml_node));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown track object: '%s' - ignored.\n", type.c_str());
|
||||
fprintf(stderr, "Unknown track object: '%s' - ignored.\n",
|
||||
type.c_str());
|
||||
}
|
||||
} // add
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
public:
|
||||
TrackObjectManager();
|
||||
~TrackObjectManager();
|
||||
void add(const XMLNode &xml_node, const Track &track);
|
||||
void add(const XMLNode &xml_node);
|
||||
void update(float dt);
|
||||
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp) const;
|
||||
void reset();
|
||||
|
||||
Reference in New Issue
Block a user