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:
hikerstk
2010-12-05 20:55:09 +00:00
parent 5c372e2f81
commit 2c15bd265f
12 changed files with 138 additions and 118 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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