Start adding support for physical objects (e.g. road cone).

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@3221 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2009-03-11 05:10:56 +00:00
parent 2a242973b1
commit 511be41e70
17 changed files with 383 additions and 222 deletions

View File

@ -41,7 +41,9 @@ CallbackManager::~CallbackManager()
MovingPhysics *mp = dynamic_cast<MovingPhysics*>(*c);
if(mp)
{
#ifndef HAVE_IRRLICHT
ssgDeRefDelete(mp);
#endif
}
else
{
@ -56,11 +58,13 @@ CallbackManager::~CallbackManager()
void CallbackManager::addCallback(Callback *c, CallbackType t)
{
m_allCallbacks[t].push_back(c);
MovingPhysics *mp = dynamic_cast<MovingPhysics*>(c);
if(mp)
{
mp->ref();
}
MovingPhysics *mp = dynamic_cast<MovingPhysics*>(c);
if(mp)
{
#ifndef HAVE_IRRLICHT
mp->ref();
#endif
}
} // addCallback
//-----------------------------------------------------------------------------
@ -74,7 +78,9 @@ void CallbackManager::clear(CallbackType cbType)
MovingPhysics *mp = dynamic_cast<MovingPhysics*>(*c);
if(mp)
{
#ifndef HAVE_IRRLICHT
ssgDeRefDelete(mp);
#endif
}
else
{

View File

@ -352,8 +352,8 @@ std::string FileManager::getHomeDir() const
{
std::string DIRNAME;
#ifdef WIN32
// For now the old windows config way is used: store a config file
// in the current directory (in other OS a special subdirectory is created)
// Try to use the APPDATA directory to store config files and highscore
// lists. If not defined, used the current directory.
std::ostringstream s;
if(getenv("APPDATA")!=NULL)
{

View File

@ -62,6 +62,9 @@ IrrDriver::IrrDriver()
file_manager->setDevice(m_device);
m_device->setWindowCaption(L"SuperTuxKart");
m_scene_manager = m_device->getSceneManager();
m_gui_env = m_device->getGUIEnvironment();
const std::string &font = file_manager->getFontFile("fonthaettenschweiler.bmp");
m_race_font = m_gui_env->getFont(font.c_str());
} // IrrDriver
// ----------------------------------------------------------------------------
@ -110,6 +113,24 @@ scene::ISceneNode *IrrDriver::addMesh(scene::IMesh *mesh)
return m_scene_manager->addMeshSceneNode(mesh);
} // addMesh
// ----------------------------------------------------------------------------
/** Removes a scene node from the scene.
* \param node The scene node to remove.
*/
void IrrDriver::removeNode(scene::ISceneNode *node)
{
node->remove();
} // removeMesh
// ----------------------------------------------------------------------------
/** Removes a mesh from the mesh cache, freeing the memory.
* \param mesh The mesh to remove.
*/
void IrrDriver::removeMesh(scene::IMesh *mesh)
{
m_scene_manager->getMeshCache()->removeMesh(mesh);
} // removeMesh
// ----------------------------------------------------------------------------
/** Adds an animated mesh to the scene.
* \param mesh The animated mesh to add.
@ -127,6 +148,15 @@ scene::ICameraSceneNode *IrrDriver::addCamera()
return m_scene_manager->addCameraSceneNode();
} // addCamera
// ----------------------------------------------------------------------------
/** Loads a texture from a file and returns the texture object.
* \param filename File name of the texture to load.
*/
video::ITexture *IrrDriver::getTexture(const std::string &filename)
{
return m_scene_manager->getVideoDriver()->getTexture(filename.c_str());
} // getTexture
// ----------------------------------------------------------------------------
/** Update, called once per frame.
* \param dt Time since last update
@ -135,6 +165,7 @@ void IrrDriver::update(float dt)
{
m_device->getVideoDriver()->beginScene(true, true, video::SColor(255,100,101,140));
m_scene_manager->drawAll();
m_device->getGUIEnvironment()->drawAll();
m_device->getVideoDriver()->endScene();
} // update
@ -155,7 +186,7 @@ bool IrrDriver::OnEvent(const irr::SEvent &event)
case irr::EET_LOG_TEXT_EVENT:
{
// Ignore 'normal' messages
if(event.LogEvent.Level>=0)
if(event.LogEvent.Level>0)
{
printf("Level %d: %s\n",
event.LogEvent.Level,event.LogEvent.Text);

View File

@ -32,7 +32,12 @@ class IrrDriver : public IEventReceiver
private:
/** The irrlicht device. */
IrrlichtDevice *m_device;
/** Irrlicht scene manager. */
scene::ISceneManager *m_scene_manager;
/** Irrlicht gui environment. */
gui::IGUIEnvironment *m_gui_env;
/** Irrlicht race font. */
irr::gui::IGUIFont *m_race_font;
public:
IrrDriver();
@ -41,9 +46,15 @@ public:
scene::ISceneManager *getSceneManager() const { return m_scene_manager; }
scene::IAnimatedMesh *getAnimatedMesh(const std::string &name);
scene::IMesh *getMesh(const std::string &name);
/** Returns the gui environment, used to add widgets to a screen. */
gui::IGUIEnvironment *getGUI() const { return m_gui_env; }
irr::gui::IGUIFont *getRaceFont() const { return m_race_font; }
bool OnEvent(const irr::SEvent &event);
video::ITexture *getTexture(const std::string &filename);
scene::ISceneNode *addOctTree(scene::IMesh *mesh);
scene::ISceneNode *addMesh(scene::IMesh *mesh);
void removeNode(scene::ISceneNode *node);
void removeMesh(scene::IMesh *mesh);
scene::ISceneNode *addAnimatedMesh(scene::IAnimatedMesh *mesh);
scene::ICameraSceneNode
*addCamera();

View File

@ -24,7 +24,6 @@
#include "gui/base_gui.hpp"
#include "gui/display_res_confirm.hpp"
#include "utils/translation.hpp"
class ConfigDisplay: public BaseGUI
{

View File

@ -27,60 +27,13 @@
#include "race_manager.hpp"
#include "material_manager.hpp"
#include "audio/sound_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "gui/font.hpp"
#include "gui/menu_manager.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
#include "utils/translation.hpp"
#undef USE_WIDGET_MANAGER
#ifdef USE_WIDGET_MANAGER
#include "gui/widget_manager.hpp"
#endif
#ifdef USE_WIDGET_MANAGER
//MAX_TOP_POS is the maximum number of racers to be shown in the bar to the
//left where the positions are drawn.
static const int MAX_TOP_POS = 10;
static const int MAX_HUMANS = 4;
enum WidgetTokens
{
WTOK_FPS,
WTOK_EMPTY1,
WTOK_CLOCK,
WTOK_EMPTY2,
WTOK_FIRST_TOP_IMG,
WTOK_LAST_TOP_IMG = WTOK_FIRST_TOP_IMG + MAX_TOP_POS,
WTOK_FIRST_TOP_TEXT,
WTOK_LAST_TOP_TEXT = WTOK_FIRST_TOP_TEXT + MAX_TOP_POS,
WTOK_FIRST_MESSAGE,
WTOK_LAST_MESSAGE = WTOK_FIRST_MESSAGE + MAX_HUMANS,
WTOK_FIRST_POWERBAR,
WTOK_LAST_POWERBAR = WTOK_FIRST_POWERBAR + MAX_HUMANS,
WTOK_FIRST_POSITION,
WTOK_LAST_POSITION = WTOK_FIRST_POSITION + MAX_HUMANS,
WTOK_MAP,
WTOK_FIRST_LAP,
WTOK_LAST_LAP = WTOK_FIRST_LAP + MAX_HUMANS,
WTOK_FIRST_WHEEL,
WTOK_LAST_WHEEL = WTOK_FIRST_WHEEL + MAX_HUMANS,
WTOK_FIRST_SPEED,
WTOK_LAST_SPEED = WTOK_FIRST_SPEED + MAX_HUMANS
};
#endif
RaceGUI::RaceGUI()
{
@ -97,7 +50,32 @@ RaceGUI::RaceGUI()
m_pos_string[9] = "9th";
m_pos_string[10] = "10th";
#ifndef HAVE_IRRLICHT
#ifdef HAVE_IRRLICHT
gui::IGUIEnvironment *gui_env = irr_driver->getGUI();
core::rect<s32> pos(user_config->m_width-60, 10,
user_config->m_width, 50);
m_time = gui_env->addStaticText(L"", pos);
m_time->setOverrideFont(irr_driver->getRaceFont());
int icon_width=40;
int icon_player_width=50;
if(user_config->m_height<600)
{
icon_width = 27;
icon_player_width = 35;
}
#ifdef NOT_READY_YET
m_icons = new gui::IGUIImage*[race_manager->getNumKarts()];
for(unsigned int i=0; i<race_manager->getNumKarts(); i++)
{
core::position2d<s32> p(0, i*20);
Kart *kart = race_manager->getKart(i);
Material *m = kart->getKartProperties()->getIconMaterial();
m = material_manager->getMaterial("track.png");
m_icons[i] = irr_driver->getGUI()->addImage(m->getTexture(), p);
}
#endif
#else
m_speed_back_icon = material_manager->getMaterial("speedback.rgb");
m_speed_back_icon->getState()->disable(GL_CULL_FACE);
m_speed_fore_icon = material_manager->getMaterial("speedfore.rgb");
@ -113,27 +91,11 @@ RaceGUI::RaceGUI()
m_fps_timer.update();
m_fps_timer.setMaxDelta(1000);
#ifdef USE_WIDGET_MANAGER
const bool HIDE_TEXT = false;
widget_manager->setInitialTextState(HIDE_TEXT, "", WGT_FNT_LRG,
WGT_FONT_RACE, WGT_WHITE );
widget_manager->addWgt( WTOK_FPS, 30, 10 );
widget_manager->addWgt( WTOK_EMPTY1, 40, 10 );
widget_manager->addWgt( WTOK_CLOCK, 30, 10 );
widget_manager->breakLine();
widget_manager->layout( WGT_AREA_TOP );
#endif
} // RaceGUI
//-----------------------------------------------------------------------------
RaceGUI::~RaceGUI()
{
#ifdef USE_WIDGET_MANAGER
widget_manager->reset();
#endif
//FIXME: does all that material stuff need freeing somehow?
} // ~Racegui
@ -197,13 +159,6 @@ RaceGUI::handle(GameAction ga, int value)
m_fps_timer.reset();
m_fps_timer.setMaxDelta(1000);
m_fps_counter=0;
#ifdef USE_WIDGET_MANAGER
widget_manager->showWgtText( WTOK_FPS );
}
else
{
widget_manager->hideWgtText( WTOK_FPS );
#endif
}
break;
case GA_DEBUG_TOGGLE_WIREFRAME:
@ -251,14 +206,12 @@ void RaceGUI::drawFPS ()
m_fps_counter = 0;
m_fps_timer.setMaxDelta(1000);
}
#ifdef USE_WIDGET_MANAGER
widget_manager->setWgtText( WTOK_FPS, m_fps_string );
#else
font_race->PrintShadow(m_fps_string,48, 0, user_config->m_height-50);
#endif
} // drawFPS
//-----------------------------------------------------------------------------
/** Displays the racing time on the screen.
*/
void RaceGUI::drawTimer ()
{
assert(RaceManager::getWorld() != NULL);
@ -267,12 +220,11 @@ void RaceGUI::drawTimer ()
char str[256];
TimeToString(RaceManager::getWorld()->getTime(), str);
#ifdef USE_WIDGET_MANAGER
widget_manager->showWgtText( WTOK_CLOCK );
widget_manager->setWgtText( WTOK_CLOCK, str );
#ifdef HAVE_IRRLICHT
m_time->setText(core::stringw(str).c_str());
#else
font_race->PrintShadow(str, 60, user_config->m_width-260,
user_config->m_height-64);
user_config->m_height-64);
#endif
} // drawTimer

View File

@ -18,8 +18,13 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_RACEGUI_H
#define HEADER_RACEGUI_H
#ifndef HEADER_RACEGUI_HPP
#define HEADER_RACEGUI_HPP
#ifdef HAVE_IRRLICHT
#include "irrlicht.h"
using namespace irr;
#endif
#include <string>
#include <vector>
@ -51,7 +56,7 @@ struct KartIconDisplayInfo
class RaceGUI: public BaseGUI
{
private:
class TimedMessage
{
public:
@ -84,18 +89,12 @@ class RaceGUI: public BaseGUI
return m_remaining_time < 0;
}
};
public:
RaceGUI();
~RaceGUI();
void update(float dt);
void select() {}
void handle(GameAction, int);
void handleKartAction(KartAction ka, int value);
void addMessage(const std::string &m, const Kart *kart, float time,
int fonst_size, int red=255, int green=0, int blue=255);
private:
#ifdef HAVE_IRRLICHT
gui::IGUIStaticText *m_time;
gui::IGUIImage **m_icons;
#endif
ulClock m_fps_timer;
int m_fps_counter;
char m_fps_string[10];
@ -128,6 +127,16 @@ private:
float ratio_x, float ratio_y );
void drawLap (const KartIconDisplayInfo* info, Kart* kart, int offset_x,
int offset_y, float ratio_x, float ratio_y );
public:
RaceGUI();
~RaceGUI();
void update(float dt);
void select() {}
void handle(GameAction, int);
void handleKartAction(KartAction ka, int value);
void addMessage(const std::string &m, const Kart *kart, float time,
int fonst_size, int red=255, int green=0, int blue=255);
};
#endif

View File

@ -217,7 +217,26 @@ int XMLNode::getXYZ(core::vector3df *value) const
if(get("y", &f)) { value->Y = f; bits |= 2; }
if(get("z", &f)) { value->Z = f; bits |= 4; }
return bits;
} // getXYZ
} // getXYZ vector3df
// ----------------------------------------------------------------------------
/** Interprets the attributes 'x', 'y', 'z' as a 3d vector and set the
* corresponding elements of value. Not all values need to be defined as
* attributes (and the correspnding elements of the vector will not be
* changed). It returns a bit field for each defined value, i.e. if x
* and y are defined, 3 is returned.
* \param value Vector to return the values in.
*/
int XMLNode::getXYZ(Vec3 *value) const
{
float f;
int bits=0;
Vec3 result = *value;
if(get("x", &f)) { value->setX(f); bits |= 1; }
if(get("y", &f)) { value->setY(f); bits |= 2; }
if(get("z", &f)) { value->setZ(f); bits |= 4; }
return bits;
} // getXYZ Vec3
// ----------------------------------------------------------------------------
/** Interprets the attributes 'h', 'p', 'r' as a 3d vector and set the
@ -236,7 +255,26 @@ int XMLNode::getHPR(core::vector3df *value) const
if(get("p", &f)) { value->Y = f; bits |= 2; }
if(get("r", &f)) { value->Z = f; bits |= 4; }
return bits;
} // getHPR
} // getHPR vector3df
// ----------------------------------------------------------------------------
/** Interprets the attributes 'h', 'p', 'r' as a 3d vector and set the
* corresponding elements of value. Not all values need to be defined as
* attributes (and the correspnding elements of the vector will not be
* changed). It returns a bit field for each defined value, i.e. if x and y
* are defined, 3 is returned.
* \param value Vector to return the values in.
*/
int XMLNode::getHPR(Vec3 *value) const
{
float f;
int bits=0;
Vec3 result = *value;
if(get("h", &f)) { value->setX(f); bits |= 1; }
if(get("p", &f)) { value->setY(f); bits |= 2; }
if(get("r", &f)) { value->setZ(f); bits |= 4; }
return bits;
} // getHPR Vec3
// ----------------------------------------------------------------------------
#endif

View File

@ -51,7 +51,9 @@ public:
int get(const std::string &attribute, std::vector<int> *value) const;
int get(core::vector3df *value) const;
int getXYZ(core::vector3df *value) const;
int getXYZ(Vec3 *value) const;
int getHPR(core::vector3df *value) const;
int getHPR(Vec3 *value) const;
/** Handy functions to test the bit pattern returned by get(vector3df*).*/
static bool hasX(int b) { return (b&1)==1; }
static bool hasY(int b) { return (b&2)==2; }

View File

@ -23,12 +23,14 @@
#include "file_manager.hpp"
#include "stk_config.hpp"
#include "graphics/irr_driver.hpp"
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
#define UCLAMP 1
#define VCLAMP 2
#ifndef HAVE_IRRLICHT
int clearSpheremap ( ssgEntity * )
{
glDisable ( GL_TEXTURE_GEN_S ) ;
@ -45,6 +47,7 @@ int setSpheremap ( ssgEntity * )
glEnable ( GL_TEXTURE_GEN_T ) ;
return true ;
} // setSpheremap
#endif
//=============================================================================
#ifndef HAVE_IRRLICHT
@ -212,6 +215,7 @@ void Material::applyToLeaf(ssgLeaf *l)
void Material::install(bool is_full_path)
{
#ifdef HAVE_IRRLICHT
m_texture = irr_driver->getTexture(file_manager->getTextureFile(m_texname));
#else
if ( isSphereMap () )
{

View File

@ -17,12 +17,17 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_MATERIAL_H
#define HEADER_MATERIAL_H
#ifndef HEADER_MATERIAL_HPP
#define HEADER_MATERIAL_HPP
#include <string>
#define _WINSOCKAPI_
#ifdef HAVE_IRRLICHT
#include "irrlicht.h"
using namespace irr;
#else
#include <plib/ssg.h>
#endif
class XMLNode;
@ -30,27 +35,28 @@ class Material
{
private:
#ifdef HAVE_IRRLICHT
video::ITexture *m_texture;
#else
ssgSimpleState *m_state;
ssgCallback m_predraw;
ssgCallback m_postdraw;
ssgSimpleState *m_state;
ssgCallback m_predraw;
ssgCallback m_postdraw;
#endif
unsigned int m_index;
std::string m_texname;
bool m_collideable;
bool m_zipper;
bool m_resetter;
bool m_ignore;
int m_clamp_tex;
bool m_lighting;
bool m_sphere_map;
bool m_transparency;
float m_alpha_ref;
float m_friction;
unsigned int m_index;
std::string m_texname;
bool m_collideable;
bool m_zipper;
bool m_resetter;
bool m_ignore;
int m_clamp_tex;
bool m_lighting;
bool m_sphere_map;
bool m_transparency;
float m_alpha_ref;
float m_friction;
/** How much the top speed is reduced per second. */
float m_slowdown;
float m_slowdown;
/** Maximum speed at which no more slow down occurs. */
float m_max_speed_fraction;
float m_max_speed_fraction;
#ifndef HAVE_IRRLICHT
bool parseBool ( char **p );
int parseInt ( char **p );
@ -73,7 +79,10 @@ public:
~Material ();
int matches ( char *tx ) ;
#ifndef HAVE_IRRLICHT
#ifdef HAVE_IRRLICHT
/** Returns the ITexture associated with this material. */
video::ITexture *getTexture() const { return m_texture; }
#else
ssgSimpleState
*getState () const { return m_state ; }
#endif

View File

@ -121,7 +121,7 @@ bool MaterialManager::pushTempMaterial(const std::string& filename)
}
try
{
m_materials.push_back(new Material(node, m_materials.size() ));
m_materials.push_back(new Material(node, m_materials.size()));
}
catch(std::exception& e)
{

View File

@ -21,16 +21,81 @@
#include <string>
#include <vector>
#ifdef HAVE_IRRLICHT
#include "irrlicht.h"
using namespace irr;
#endif
#define _WINSOCKAPI_
#include <plib/sg.h>
#include "file_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/mesh_tools.hpp"
#include "graphics/scene.hpp"
#include "io/xml_node.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
#include "utils/coord.hpp"
#include "utils/ssg_help.hpp"
#include "utils/string_utils.hpp"
// -----------------------------------------------------------------------------
#ifdef HAVE_IRRLICHT
MovingPhysics::MovingPhysics(const XMLNode *xml_node)
{
std::string model_name;
const Track *track=RaceManager::getTrack();
xml_node->get("model", &model_name);
std::string full_path = file_manager->getTrackFile(model_name,
track->getIdent());
scene::IAnimatedMesh *obj = irr_driver->getAnimatedMesh(full_path);
if(!obj)
{
// If the model isn't found in the track directory, look
// in STK's model directory.
full_path = file_manager->getModelFile(model_name);
obj = irr_driver->getAnimatedMesh(full_path);
if(!obj)
{
fprintf(stderr, "Warning: '%s' in '%s' not found and is ignored.\n",
xml_node->getName().c_str(), model_name.c_str());
} // if(!obj)
}
m_mesh = obj->getMesh(0);
m_node = irr_driver->addMesh(m_mesh);
Vec3 xyz(0,0,0);
int result = xml_node->getXYZ(&xyz);
if(!XMLNode::hasZ(result)) // needs height
{
xyz.setZ(RaceManager::getTrack()->getTerrainHeight(xyz));
}
Vec3 hpr(0,0,0);
result = xml_node->getHPR(&hpr);
if(!XMLNode::hasP(result) ||
!XMLNode::hasR(result)) // Needs perhaps pitch and roll
{
}
m_node->setPosition(xyz.toIrrVector());
m_node->setRotation(hpr.toIrrHPR());
m_init_pos.setIdentity();
m_init_pos.setOrigin(xyz);
m_node->setMaterialFlag(video::EMF_LIGHTING, false);
m_shape = NULL;
m_body = NULL;
m_motion_state = NULL;
m_mass = 1;
std::string shape;
xml_node->get("shape", &shape);
xml_node->get("mass", &m_mass);
m_body_type = MP_NONE;
if (shape=="cone" ) m_body_type = MP_CONE;
else if(shape=="box" ) m_body_type = MP_BOX;
else if(shape=="sphere" ) m_body_type = MP_SPHERE;
} // MovingPhysics
#else
MovingPhysics::MovingPhysics(const std::string data)
: ssgTransform(), Callback()
{
@ -78,6 +143,7 @@ MovingPhysics::MovingPhysics(const std::string data)
parameters.erase(parameters.begin());
}
} // MovingPhysics
#endif
// -----------------------------------------------------------------------------
MovingPhysics::~MovingPhysics()
@ -86,7 +152,10 @@ MovingPhysics::~MovingPhysics()
delete m_body;
delete m_motion_state;
delete m_shape;
#ifdef HAVE_IRRLICHT
#else
stk_scene->remove(this);
#endif
} // ~MovingPhysics
// -----------------------------------------------------------------------------
@ -102,7 +171,8 @@ MovingPhysics::~MovingPhysics()
recomputed by going up in the scene graph and multiplying the transforms. */
void MovingPhysics::init()
{
#ifdef HAVE_IRRLICHT
#else
// 1. Remove the object from the graph and attach it to the root
// -------------------------------------------------------------
if(getNumParents()>1)
@ -152,11 +222,16 @@ void MovingPhysics::init()
p=p->getParent(0);
}
} // while
#endif
// 3. Determine size of the object
// -------------------------------
Vec3 min, max;
#ifdef HAVE_IRRLICHT
MeshTools::minMax3D(m_mesh, &min, &max);
#else
SSGHelp::MinMax(this, &min, &max);
#endif
Vec3 extend = max-min;
m_half_height = 0.5f*(extend.getZ());
switch (m_body_type)
@ -164,17 +239,25 @@ void MovingPhysics::init()
case MP_CONE: {
float radius = 0.5f*std::max(extend.getX(), extend.getY());
m_shape = new btConeShapeZ(radius, extend.getZ());
#ifdef HAVE_IRRLICHT
#else
setName("cone");
#endif
break;
}
case MP_BOX: m_shape = new btBoxShape(0.5*extend);
#ifndef HAVE_IRRLICHT
setName("box");
#endif
break;
case MP_SPHERE: {
float radius = std::max(extend.getX(), extend.getY());
radius = 0.5f*std::max(radius, extend.getZ());
m_shape = new btSphereShape(radius);
#ifndef HAVE_IRRLICHT
setName("sphere");
#endif
break;
}
case MP_NONE: fprintf(stderr, "WARNING: Uninitialised moving shape\n");
@ -183,9 +266,14 @@ void MovingPhysics::init()
// 4. Create the rigid object
// --------------------------
#ifdef HAVE_IRRLICHT
Vec3 pos = m_init_pos.getOrigin();
pos.setZ(m_init_pos.getOrigin().getZ()+m_half_height);
m_init_pos.setOrigin(pos);
#else
m_init_pos.setIdentity();
m_init_pos.setOrigin(btVector3(pos[3][0],pos[3][1],pos[3][2]+m_half_height));
#endif
m_motion_state = new btDefaultMotionState(m_init_pos);
btVector3 inertia;
m_shape->calculateLocalInertia(m_mass, inertia);
@ -208,10 +296,14 @@ void MovingPhysics::update(float dt)
if(c.getXYZ().getZ()<-100)
{
m_body->setCenterOfMassTransform(m_init_pos);
c.setXYZ(m_init_pos.getOrigin());
c.setXYZ(m_init_pos.getOrigin());
}
#ifdef HAVE_IRRLICHT
m_node->setPosition(c.getXYZ().toIrrVector());
m_node->setRotation(c.getHPR().toIrrHPR());
#else
setTransform(const_cast<sgCoord*>(&c.toSgCoord()));
#endif
} // update
// -----------------------------------------------------------------------------

View File

@ -17,9 +17,13 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_MOVING_PHYSICS_H
#define HEADER_MOVING_PHYSICS_H
#ifndef HEADER_MOVING_PHYSICS_HPP
#define HEADER_MOVING_PHYSICS_HPP
#include <string>
#ifdef HAVE_IRRLICHT
#include "irrlicht.h"
using namespace irr;
#endif
#define _WINSOCKAPI_
#include <plib/ssg.h>
#include "btBulletDynamicsCommon.h"
@ -27,8 +31,16 @@
#include "user_pointer.hpp"
class Vec3;
#ifdef HAVE_IRRLICHT
class scene::IAnimatedMesh;
class XMLNode;
#endif
#ifdef HAVE_IRRLICHT
class MovingPhysics : public Callback
#else
class MovingPhysics : public ssgTransform, public Callback
#endif
{
public:
enum bodyTypes {MP_NONE, MP_CONE, MP_BOX, MP_SPHERE};
@ -42,8 +54,16 @@ protected:
float m_mass;
UserPointer m_user_pointer;
btTransform m_init_pos;
#ifdef HAVE_IRRLICHT
scene::IMesh *m_mesh;
scene::ISceneNode *m_node;
#endif
public:
#ifdef HAVE_IRRLICHT
MovingPhysics (const XMLNode *node);
#else
MovingPhysics (const std::string data);
#endif
~MovingPhysics ();
void update (float dt);
void init ();

View File

@ -91,6 +91,16 @@ Track::~Track()
*/
void Track::cleanup()
{
#ifdef HAVE_IRRLICHT
for(unsigned int i=0; i<m_all_nodes.size(); i++)
{
irr_driver->removeNode(m_all_nodes[i]);
}
for(unsigned int i=0; i<m_all_meshes.size(); i++)
{
irr_driver->removeMesh(m_all_meshes[i]);
}
#endif
delete m_non_collision_mesh;
delete m_track_mesh;
@ -1179,41 +1189,36 @@ void Track::createPhysicsModel()
#ifdef HAVE_IRRLICHT
void Track::convertTrackToBullet(const scene::IMesh *mesh)
{
for(unsigned int i=0; i<mesh->getMeshBufferCount(); i++) {
scene::IMeshBuffer *mb = mesh->getMeshBuffer(i);
// FIXME: take translation/rotation into accou
if(mb->getVertexType()!=video::EVT_STANDARD) {
fprintf(stderr, "WARNING: Physics::convertTrack: Ignoring type '%d'!",
mb->getVertexType());
continue;
}
video::SMaterial irrMaterial=mb->getMaterial();
video::ITexture* t=irrMaterial.getTexture(0);
// FIXME: if no material is given, perhaps define a default?
const Material* material=0;
if(t) {
//material=g_MaterialManager->getMaterial(t->getName());
printf("%s\n",t->getName());
}
for(unsigned int i=0; i<mesh->getMeshBufferCount(); i++) {
scene::IMeshBuffer *mb = mesh->getMeshBuffer(i);
// FIXME: take translation/rotation into accou
if(mb->getVertexType()!=video::EVT_STANDARD) {
fprintf(stderr, "WARNING: Physics::convertTrack: Ignoring type '%d'!",
mb->getVertexType());
continue;
}
video::SMaterial irrMaterial=mb->getMaterial();
video::ITexture* t=irrMaterial.getTexture(0);
// FIXME: if no material is given, perhaps define a default?
const Material* material=0;
TriangleMesh *tmesh = m_track_mesh;
if(t) {
material=material_manager->getMaterial(std::string(t->getName().c_str()));
if(material->isZipper()) tmesh = m_non_collision_mesh;
}
u16 *mbIndices = mb->getIndices();
Vec3 vertices[3];
irr::video::S3DVertex* mbVertices=(video::S3DVertex*)mb->getVertices();
for(unsigned int j=0; j<mb->getIndexCount(); j+=3) {
for(unsigned int k=0; k<3; k++) {
int indx=mbIndices[j+k];
// FIXME: notice: irrlicht's and STK's axis are different
// (STK: Z up, irrlicht: Y up). We might want to change
// this as well, makes it easier to work with bullet and
// irrlicht together, without having to swap indices.
vertices[k] = Vec3(mbVertices[indx].Pos.X,
mbVertices[indx].Pos.Z,
mbVertices[indx].Pos.Y );
} // for k
m_track_mesh->addTriangle(vertices[0], vertices[1],
vertices[2], material );
} // for j
} // for i<getMeshBufferCount
u16 *mbIndices = mb->getIndices();
Vec3 vertices[3];
irr::video::S3DVertex* mbVertices=(video::S3DVertex*)mb->getVertices();
for(unsigned int j=0; j<mb->getIndexCount(); j+=3) {
for(unsigned int k=0; k<3; k++) {
int indx=mbIndices[j+k];
vertices[k] = Vec3(mbVertices[indx].Pos);
} // for k
if(tmesh) tmesh->addTriangle(vertices[0], vertices[1],
vertices[2], material );
} // for j
} // for i<getMeshBufferCount
} // convertTrackToBullet
@ -1366,35 +1371,8 @@ void Track::loadTrackModel()
if(name=="track") continue;
if(name=="object")
{
std::string model_name;
node->get("model", &model_name);
std::string full_path = file_manager->getTrackFile(model_name,
getIdent());
scene::IAnimatedMesh *obj = irr_driver->getAnimatedMesh(full_path);
if(!obj)
{
fprintf(stderr, "Warning: '%s' in '%s' not found and is ignored.\n",
node->getName().c_str(), model_name.c_str());
continue;
}
scene::IMesh *mesh = obj->getMesh(0);
m_all_meshes.push_back(mesh);
scene::ISceneNode *scene_node = irr_driver->addOctTree(mesh);
core::vector3df xyz(0,0,0);
int result = node->get(&xyz);
if(!XMLNode::hasZ(result)) // needs height
{
}
core::vector3df hpr(0,0,0);
result = node->get(&hpr);
if(!XMLNode::hasP(result) ||
!XMLNode::hasR(result)) // Needs perhaps pitch and roll
{
}
scene_node->setPosition(xyz);
scene_node->setRotation(hpr);
m_all_nodes.push_back(scene_node);
scene_node->setMaterialFlag(video::EMF_LIGHTING, false);
MovingPhysics *mp = new MovingPhysics(node);
callback_manager->addCallback(mp, CB_TRACK);
}
else if(name=="banana" || name=="item" ||
name=="small-nitro" || name=="big-nitro")
@ -1404,16 +1382,10 @@ void Track::loadTrackModel()
else if(name=="item" ) type = Item::ITEM_BONUS_BOX;
else if(name=="small-nitro") type = Item::ITEM_SILVER_COIN;
else type = Item::ITEM_GOLD_COIN;
core::vector3df xyz;
int bits = node->get(&xyz);
Vec3 xyz;
int bits = node->getXYZ(&xyz);
// Height is needed if bit 2 (for z) is not set
itemCommand(&xyz, type, /* need_height */ !XMLNode::hasZ(bits) );
}
else if(name=="item")
{
}
else if(name=="small-nitro" || node->getName()=="big-nitro")
{
itemCommand(xyz, type, /* need_height */ !XMLNode::hasZ(bits) );
}
else
{
@ -1667,7 +1639,7 @@ void Track::loadTrackModel()
//-----------------------------------------------------------------------------
#ifdef HAVE_IRRLICHT
void Track::itemCommand(core::vector3df *xyz, Item::ItemType type,
void Track::itemCommand(const Vec3 &xyz, Item::ItemType type,
int bNeedHeight)
{
// Some modes (e.g. time trial) don't have any bonus boxes
@ -1675,29 +1647,21 @@ void Track::itemCommand(core::vector3df *xyz, Item::ItemType type,
!RaceManager::getWorld()->enableBonusBoxes())
return;
Vec3 loc(xyz);
// if only 2d coordinates are given, let the item fall from very high
if(bNeedHeight)
{
Vec3 pos(*xyz);
float m_HoT;
Vec3 m_normal;
const Material *material;
pos.setZ(1000);
getTerrainInfo(pos, &m_HoT, &m_normal, &material);
xyz->Z = m_HoT;
loc.setZ(1000);
loc.setZ(getTerrainHeight(loc));
}
// Even if 3d data are given, make sure that the item is on the ground
//xyz->Z = irr_dirver->getHeight( m_model, *xyz ) + 0.06f;
Vec3 loc(*xyz);
// Don't tilt the items, since otherwise the rotation will look odd,
// i.e. the items will not rotate around the normal, but 'wobble'
// around.
Vec3 normal(0, 0, 0.0f);
item_manager->newItem(type, loc, normal);
} // itemCommand
// ----------------------------------------------------------------------------
#else
void Track::itemCommand (sgVec3 *xyz, int type, int bNeedHeight )
{
@ -1719,9 +1683,9 @@ void Track::itemCommand (sgVec3 *xyz, int type, int bNeedHeight )
Vec3 normal(0, 0, 0.0f);
item_manager->newItem((Item::ItemType)type, loc, normal);
} // itemCommand
// ----------------------------------------------------------------------------
#endif
// ----------------------------------------------------------------------------
void Track::getTerrainInfo(const Vec3 &pos, float *hot, Vec3 *normal,
const Material **material) const
{
@ -1772,3 +1736,18 @@ void Track::getTerrainInfo(const Vec3 &pos, float *hot, Vec3 *normal,
// assume two karts falling down, one over the other. Bullet does not
// have any triangle/material information in this case!
} // getTerrainInfo
// ----------------------------------------------------------------------------
/** Simplified version to determine only the height of the terrain.
* \param pos Position at which to determine the height (x,y coordinates
* are only used).
* \return The height at the x,y coordinates.
*/
float Track::getTerrainHeight(const Vec3 &pos) const
{
float hot;
Vec3 normal;
const Material *m;
getTerrainInfo(pos, &hot, &normal, &m);
return hot;
} // getTerrainHeight

View File

@ -220,9 +220,10 @@ public:
const Vec3& getCameraPosition () const {return m_camera_final_position;}
const Vec3& getCameraHPR () const {return m_camera_final_hpr; }
btTransform getStartTransform (unsigned int pos) const;
void getTerrainInfo(const Vec3 &pos, float *hot, Vec3* normal,
const Material **material) const;
void createPhysicsModel ();
void getTerrainInfo(const Vec3 &pos, float *hot, Vec3* normal,
const Material **material) const;
float getTerrainHeight(const Vec3 &pos) const;
void createPhysicsModel();
void glVtx (sgVec2 v, float x_offset, float y_offset) const
{
glVertex2f(
@ -233,7 +234,7 @@ public:
private:
void loadTrack(const std::string &filename);
#ifdef HAVE_IRRLICHT
void itemCommand(core::vector3df *xyz, Item::ItemType item_type,
void itemCommand(const Vec3 &xyz, Item::ItemType item_type,
int bNeedHeight);
#else
void itemCommand(sgVec3 *xyz, int item_type, int bNeedHeight);

View File

@ -37,7 +37,15 @@ private:
public:
#ifdef HAVE_IRRLICHT
inline Vec3(const core::vector3df &v) : btVector3(v.X, v.Y, v.Z) {}
/** Convert an irrlicht vector3df into the internal (bullet) format.
* Irrlicht's and STK's axis are different (STK: Z up, irrlicht: Y up).
* We might want to change this as well, makes it easier to work with
* bullet and irrlicht together, without having to swap indices (bullet
* can handle any axis ordering). Note that toIrrVector swaps the
* axis as well (so a vector3df can be stored in and restored from
* a vec3).
*/
inline Vec3(const core::vector3df &v) : btVector3(v.X, v.Z, v.Y) {}
#endif
inline Vec3(sgVec3 a) : btVector3(a[0], a[1], a[2]) {}
inline Vec3(const btVector3& a) : btVector3(a) {}