From 511be41e7045eddb22e82a22ba4bc47743c63747 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 11 Mar 2009 05:10:56 +0000 Subject: [PATCH] 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 --- src/callback_manager.cpp | 16 ++-- src/file_manager.cpp | 4 +- src/graphics/irr_driver.cpp | 33 ++++++- src/graphics/irr_driver.hpp | 11 +++ src/gui/config_display.hpp | 1 - src/gui/race_gui.cpp | 112 +++++++----------------- src/gui/race_gui.hpp | 35 +++++--- src/io/xml_node.cpp | 42 ++++++++- src/io/xml_node.hpp | 2 + src/material.cpp | 4 + src/material.hpp | 49 ++++++----- src/material_manager.cpp | 2 +- src/physics/moving_physics.cpp | 100 +++++++++++++++++++++- src/physics/moving_physics.hpp | 24 +++++- src/tracks/track.cpp | 151 ++++++++++++++------------------- src/tracks/track.hpp | 9 +- src/utils/vec3.hpp | 10 ++- 17 files changed, 383 insertions(+), 222 deletions(-) diff --git a/src/callback_manager.cpp b/src/callback_manager.cpp index 33861ec4d..1a5a3e5fc 100644 --- a/src/callback_manager.cpp +++ b/src/callback_manager.cpp @@ -41,7 +41,9 @@ CallbackManager::~CallbackManager() MovingPhysics *mp = dynamic_cast(*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(c); - if(mp) - { - mp->ref(); - } + MovingPhysics *mp = dynamic_cast(c); + if(mp) + { +#ifndef HAVE_IRRLICHT + mp->ref(); +#endif + } } // addCallback //----------------------------------------------------------------------------- @@ -74,7 +78,9 @@ void CallbackManager::clear(CallbackType cbType) MovingPhysics *mp = dynamic_cast(*c); if(mp) { +#ifndef HAVE_IRRLICHT ssgDeRefDelete(mp); +#endif } else { diff --git a/src/file_manager.cpp b/src/file_manager.cpp index 9cd11fdaa..b17d0498f 100644 --- a/src/file_manager.cpp +++ b/src/file_manager.cpp @@ -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) { diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 29b56ad84..e4675d298 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -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); diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index de89ba53d..78484e2bc 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -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(); diff --git a/src/gui/config_display.hpp b/src/gui/config_display.hpp index f0bf1a0d3..c97aa6916 100644 --- a/src/gui/config_display.hpp +++ b/src/gui/config_display.hpp @@ -24,7 +24,6 @@ #include "gui/base_gui.hpp" #include "gui/display_res_confirm.hpp" -#include "utils/translation.hpp" class ConfigDisplay: public BaseGUI { diff --git a/src/gui/race_gui.cpp b/src/gui/race_gui.cpp index 549c650d6..7cae3c990 100644 --- a/src/gui/race_gui.cpp +++ b/src/gui/race_gui.cpp @@ -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 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; igetNumKarts(); i++) + { + core::position2d 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 diff --git a/src/gui/race_gui.hpp b/src/gui/race_gui.hpp index 7fd9269bd..076fe996d 100644 --- a/src/gui/race_gui.hpp +++ b/src/gui/race_gui.hpp @@ -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 #include @@ -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 diff --git a/src/io/xml_node.cpp b/src/io/xml_node.cpp index 898b3e51c..7f2da61cd 100644 --- a/src/io/xml_node.cpp +++ b/src/io/xml_node.cpp @@ -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 diff --git a/src/io/xml_node.hpp b/src/io/xml_node.hpp index 38b3d6138..3b0a4daf8 100644 --- a/src/io/xml_node.hpp +++ b/src/io/xml_node.hpp @@ -51,7 +51,9 @@ public: int get(const std::string &attribute, std::vector *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; } diff --git a/src/material.cpp b/src/material.cpp index a5a214182..2a592e8de 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -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 () ) { diff --git a/src/material.hpp b/src/material.hpp index d086d5971..d3798ab4b 100644 --- a/src/material.hpp +++ b/src/material.hpp @@ -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 #define _WINSOCKAPI_ +#ifdef HAVE_IRRLICHT +#include "irrlicht.h" +using namespace irr; +#else #include +#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 diff --git a/src/material_manager.cpp b/src/material_manager.cpp index 32d8ea457..76c89ef19 100644 --- a/src/material_manager.cpp +++ b/src/material_manager.cpp @@ -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) { diff --git a/src/physics/moving_physics.cpp b/src/physics/moving_physics.cpp index 47366916d..7c4c89af0 100644 --- a/src/physics/moving_physics.cpp +++ b/src/physics/moving_physics.cpp @@ -21,16 +21,81 @@ #include #include +#ifdef HAVE_IRRLICHT +#include "irrlicht.h" +using namespace irr; +#endif #define _WINSOCKAPI_ #include +#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(&c.toSgCoord())); +#endif } // update // ----------------------------------------------------------------------------- diff --git a/src/physics/moving_physics.hpp b/src/physics/moving_physics.hpp index f0ccc4bc4..f512133b3 100644 --- a/src/physics/moving_physics.hpp +++ b/src/physics/moving_physics.hpp @@ -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 +#ifdef HAVE_IRRLICHT +#include "irrlicht.h" +using namespace irr; +#endif #define _WINSOCKAPI_ #include #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 (); diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index c53d9226c..788140c31 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -91,6 +91,16 @@ Track::~Track() */ void Track::cleanup() { +#ifdef HAVE_IRRLICHT + for(unsigned int i=0; iremoveNode(m_all_nodes[i]); + } + for(unsigned int i=0; iremoveMesh(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; igetMeshBufferCount(); 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; igetMeshBufferCount(); 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; jgetIndexCount(); 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 igetIndices(); + Vec3 vertices[3]; + irr::video::S3DVertex* mbVertices=(video::S3DVertex*)mb->getVertices(); + for(unsigned int j=0; jgetIndexCount(); 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 iget("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 diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 39f849aa7..4d139a95c 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -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); diff --git a/src/utils/vec3.hpp b/src/utils/vec3.hpp index 6bf92f49c..46837ebe6 100644 --- a/src/utils/vec3.hpp +++ b/src/utils/vec3.hpp @@ -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) {}