diff --git a/src/Makefile.am b/src/Makefile.am index 4db970ff2..72163bac6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,8 @@ supertuxkart_SOURCES = \ graphics/particle_kind.hpp \ graphics/particle_kind_manager.cpp \ graphics/particle_kind_manager.hpp \ + graphics/rain.cpp \ + graphics/rain.hpp \ graphics/shadow.cpp \ graphics/shadow.hpp \ graphics/skid_marks.cpp \ diff --git a/src/graphics/rain.cpp b/src/graphics/rain.cpp new file mode 100644 index 000000000..36ba55c24 --- /dev/null +++ b/src/graphics/rain.cpp @@ -0,0 +1,121 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "graphics/irr_driver.hpp" +#include "graphics/material_manager.hpp" +#include "graphics/material.hpp" +#include "graphics/rain.h" + +const float RAIN_RADIUS[RAIN_RING_COUNT] = { 6.0f, 12.0f, 24.0f }; +const float RAIN_Y_TO = 25.0f; +const float RAIN_Y_FROM = -10.0f; +const float RAIN_DY = 2.5f; + +const float TEXTURE_X_TILES[RAIN_RING_COUNT] = { 3.5f, 5.0f, 8.0f }; +const float TEXTURE_Y_TILES[RAIN_RING_COUNT] = { 6.0f, 4.0f, 4.0f}; + + +Rain::Rain(irr::scene::ISceneNode* parent) +{ + m_y = 0.0f; + + Material* m = material_manager->getMaterial("rain.png"); + assert(m != NULL); + + for (int r=0; rMaterial.setTexture(0, m->getTexture()); + m->setMaterialProperties(&buffer->Material); + buffer->Material.BackfaceCulling = false; + + m_materials.push_back(&buffer->Material); + + video::S3DVertex v; + v.Color.set(255,255,255,255); + + // create a cylinder mesh + const int VERTICES = 17; + + for (int vid=0; vidVertices.push_back(v); + + v.Pos.Y = RAIN_Y_FROM; + + v.TCoords.Y = 0.0f; + buffer->Vertices.push_back(v); + + if (vid > 0) + { + buffer->Indices.push_back(vid-2); + buffer->Indices.push_back(vid-1); + buffer->Indices.push_back(vid); + buffer->Indices.push_back(vid-1); + buffer->Indices.push_back(vid); + buffer->Indices.push_back(vid+1); + } + } + + scene::SMesh* mesh = new scene::SMesh(); + mesh->addMeshBuffer(buffer); + mesh->recalculateBoundingBox(); + + m_node[r] = irr_driver->addMesh(mesh); + if (parent != NULL) m_node[r]->setParent(parent); + mesh->drop(); + + buffer->drop(); + } +} + +void Rain::update(float dt) +{ + m_y = m_y + dt*RAIN_DY; + if (m_y > 1.0f) m_y = fmod(m_y, 1.0f); + + //const int count = m_materials.size(); + for (int m=0; mgetMaterial(0).getTextureMatrix(0); + + matrix.setTextureTranslate(0, m_y); + } +} + +void Rain::setPosition(const core::vector3df& position) +{ + for (int m=0; msetPosition(position); + } +} + diff --git a/src/graphics/rain.hpp b/src/graphics/rain.hpp new file mode 100644 index 000000000..ca3e2aae0 --- /dev/null +++ b/src/graphics/rain.hpp @@ -0,0 +1,39 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// 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_RAIN_HPP +#define HEADER_RAIN_HPP + +#include +const int RAIN_RING_COUNT = 3; + +class Rain +{ + irr::scene::ISceneNode* m_node[RAIN_RING_COUNT]; + std::vector m_materials; + + float m_y; + +public: + Rain(irr::scene::ISceneNode* parent); + void update(float dt); + void setPosition(const irr::core::vector3df& position); +}; + +#endif diff --git a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj index a238b28ad..841b2a9e7 100644 --- a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj +++ b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj @@ -370,6 +370,7 @@ 9556A881119EF976009C558F /* options_screen_video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9556A87E119EF976009C558F /* options_screen_video.cpp */; }; 955764E612FB67EF005CE479 /* btKartRaycast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955764E412FB67EF005CE479 /* btKartRaycast.cpp */; }; 95591C4412A5E91E00FB1E95 /* fribidi.framework in Copy frameworks */ = {isa = PBXBuildFile; fileRef = 954E486911B19C4100B1DF63 /* fribidi.framework */; }; + 9559DE7F12FF777600350DE8 /* rain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9559DE7E12FF777600350DE8 /* rain.cpp */; }; 955DE88310042701006A4F3C /* check_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955DE88110042701006A4F3C /* check_manager.cpp */; }; 955DE88C1004273B006A4F3C /* check_structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955DE8871004273B006A4F3C /* check_structure.cpp */; }; 9560368C12187EFB00EB96C4 /* layout_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9560368A12187EFB00EB96C4 /* layout_manager.cpp */; }; @@ -989,6 +990,8 @@ 9556A87F119EF976009C558F /* options_screen_video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = options_screen_video.hpp; path = ../../states_screens/options_screen_video.hpp; sourceTree = SOURCE_ROOT; }; 955764E412FB67EF005CE479 /* btKartRaycast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = btKartRaycast.cpp; path = ../../physics/btKartRaycast.cpp; sourceTree = SOURCE_ROOT; }; 955764E512FB67EF005CE479 /* btKartRaycast.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = btKartRaycast.hpp; path = ../../physics/btKartRaycast.hpp; sourceTree = SOURCE_ROOT; }; + 9559DE7D12FF777600350DE8 /* rain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rain.h; path = games/supertuxkart/src/graphics/rain.h; sourceTree = SYSTEM_DEVELOPER_DIR; }; + 9559DE7E12FF777600350DE8 /* rain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = rain.cpp; path = games/supertuxkart/src/graphics/rain.cpp; sourceTree = SYSTEM_DEVELOPER_DIR; }; 955DE88110042701006A4F3C /* check_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = check_manager.cpp; path = ../../tracks/check_manager.cpp; sourceTree = SOURCE_ROOT; }; 955DE88210042701006A4F3C /* check_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = check_manager.hpp; path = ../../tracks/check_manager.hpp; sourceTree = SOURCE_ROOT; }; 955DE8871004273B006A4F3C /* check_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = check_structure.cpp; path = ../../tracks/check_structure.cpp; sourceTree = SOURCE_ROOT; }; @@ -1547,6 +1550,8 @@ 9542FD4B12D3E0D700C00366 /* particle_kind.hpp */, 9528C71412D69494006E9167 /* particle_kind_manager.cpp */, 9528C71512D69494006E9167 /* particle_kind_manager.hpp */, + 9559DE7E12FF777600350DE8 /* rain.cpp */, + 9559DE7D12FF777600350DE8 /* rain.h */, 952A153D103F66D600B1895D /* shadow.cpp */, 952A153E103F66D600B1895D /* shadow.hpp */, 952A153F103F66D600B1895D /* skid_marks.cpp */, @@ -3334,6 +3339,7 @@ 95557B8612FA14AA00CC458E /* btQuickprof.cpp in Sources */, 95557B8712FA14AA00CC458E /* btSerializer.cpp in Sources */, 955764E612FB67EF005CE479 /* btKartRaycast.cpp in Sources */, + 9559DE7F12FF777600350DE8 /* rain.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 2e348a977..95334b739 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -33,6 +33,7 @@ #include "graphics/particle_emitter.hpp" #include "graphics/particle_kind.hpp" #include "graphics/particle_kind_manager.hpp" +#include "graphics/rain.h" #include "graphics/shadow.hpp" #include "graphics/skid_marks.hpp" #include "graphics/slip_stream.hpp" @@ -64,7 +65,7 @@ * number of karts). This is used to determine the start position. * \param init_transform The initial position and rotation for this kart. */ -Kart::Kart (const std::string& ident, int position, +Kart::Kart (const std::string& ident, Track* track, int position, const btTransform& init_transform, RaceManager::KartType type) : TerrainInfo(1), Moveable(), EmergencyAnimation(this), MaxSpeed(this), m_powerup(this) @@ -92,7 +93,7 @@ Kart::Kart (const std::string& ident, int position, m_finish_time = 0.0f; m_shadow_enabled = false; m_shadow = NULL; - m_terrain_particles = NULL; + m_terrain_particles = NULL; m_water_splash_system = NULL; m_nitro = NULL; m_slipstream = NULL; @@ -101,6 +102,7 @@ Kart::Kart (const std::string& ident, int position, m_controller = NULL; m_saved_controller = NULL; m_flying = false; + m_rain = NULL; m_view_blocked_by_plunger = 0; @@ -151,7 +153,7 @@ Kart::Kart (const std::string& ident, int position, animations = false; } - loadData(animations); + loadData(type, track, animations); reset(); } // Kart @@ -746,10 +748,15 @@ void Kart::update(float dt) m_attachment->update(dt); //smoke drawing control point - if (UserConfigParams::m_graphical_effects && m_terrain_particles) + if (UserConfigParams::m_graphical_effects) { - m_terrain_particles->update(); - m_water_splash_system->update(); + if (m_terrain_particles) m_terrain_particles->update(); + if (m_water_splash_system) m_water_splash_system->update(); + if (m_rain) + { + m_rain->setPosition( getCamera()->getCameraSceneNode()->getPosition() ); + m_rain->update(dt); + } } // UserConfigParams::m_graphical_effects m_nitro->update(); @@ -1449,7 +1456,7 @@ void Kart::updatePhysics(float dt) /** Attaches the right model, creates the physics and loads all special * effects (particle systems etc.) */ -void Kart::loadData(bool animatedModel) +void Kart::loadData(RaceManager::KartType type, Track* track, bool animatedModel) { m_kart_model->attachModel(&m_node, animatedModel); // Attachment must be created after attachModel, since only then the @@ -1477,6 +1484,12 @@ void Kart::loadData(bool animatedModel) std::cerr << "[Kart::loadData] " << e.what() << std::endl; } } + + if (UserConfigParams::m_weather_effects && track->getWeatherType() == WEATHER_RAIN && type == RaceManager::KT_PLAYER) + { + m_rain = new Rain(NULL); + } + //m_water_splash_system = new WaterSplash(this); m_water_splash_system = new ParticleEmitter(ParticleKindManager::get()->getParticles("splash.xml"), diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 219680397..b04995af1 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -49,6 +49,7 @@ class SkidMarks; class SlipStream; class WaterSplash; class ParticleEmitter; +class Rain; /** The main kart class. All type of karts are of this object, but with * different controllers. The controllers are what turn a kart into a @@ -146,6 +147,8 @@ private: /** Handles all slipstreaming. */ SlipStream *m_slipstream; + + Rain *m_rain; float m_wheel_rotation; @@ -188,12 +191,12 @@ protected: KartModel* m_kart_model; public: - Kart(const std::string& ident, int position, + Kart(const std::string& ident, Track* track, int position, const btTransform& init_transform, RaceManager::KartType type); virtual ~Kart(); unsigned int getWorldKartId() const { return m_world_kart_id; } void setWorldKartId(unsigned int n) { m_world_kart_id=n; } - void loadData(bool animatedModel); + void loadData(RaceManager::KartType type, Track* track, bool animatedModel); virtual void updateGraphics(const Vec3& off_xyz, const btQuaternion& off_rotation); void createPhysics (); diff --git a/src/modes/profile_world.cpp b/src/modes/profile_world.cpp index 8026355d8..ade36a626 100644 --- a/src/modes/profile_world.cpp +++ b/src/modes/profile_world.cpp @@ -91,7 +91,7 @@ Kart *ProfileWorld::createKart(const std::string &kart_ident, int index, race_manager->getNumberOfKarts()-1); btTransform init_pos = m_track->getStartTransform(index); - Kart *new_kart = new Kart(prof_kart_id, index+1, init_pos, RaceManager::KT_AI); + Kart *new_kart = new Kart(prof_kart_id, m_track, index+1, init_pos, RaceManager::KT_AI); Controller *controller = loadAIController(new_kart); new_kart->setController(controller); diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 9ffe99ddc..3225dc232 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -174,7 +174,7 @@ Kart *World::createKart(const std::string &kart_ident, int index, { int position = index+1; btTransform init_pos = m_track->getStartTransform(index); - Kart *new_kart = new Kart(kart_ident, position, init_pos, race_manager->getKartType(index)); + Kart *new_kart = new Kart(kart_ident, m_track, position, init_pos, race_manager->getKartType(index)); Controller *controller = NULL; switch(race_manager->getKartType(index)) { diff --git a/src/network/network_kart.cpp b/src/network/network_kart.cpp index c22cf8c21..53214fe0a 100644 --- a/src/network/network_kart.cpp +++ b/src/network/network_kart.cpp @@ -24,10 +24,10 @@ /** A network kart. On the server, it receives its control information (steering etc) from the network manager. */ -NetworkKart::NetworkKart(const std::string &kart_name, int position, +NetworkKart::NetworkKart(const std::string &kart_name, Track* track, int position, const btTransform &init_transform, int global_player_id, RaceManager::KartType type) - : Kart(kart_name, position, init_transform, type) + : Kart(kart_name, track, position, init_transform, type) { m_global_player_id = global_player_id; } // NetworkKart diff --git a/src/network/network_kart.hpp b/src/network/network_kart.hpp index 0450c7341..a58d5f1c5 100644 --- a/src/network/network_kart.hpp +++ b/src/network/network_kart.hpp @@ -22,12 +22,14 @@ #include "karts/kart.hpp" +class Track; + class NetworkKart : public Kart { private: int m_global_player_id; // to identify this kart to the network manager public: - NetworkKart(const std::string& kart_name, int position, + NetworkKart(const std::string& kart_name, Track* track, int position, const btTransform& init_transform, int global_player_id, RaceManager::KartType type); void setControl(const KartControl& kc); diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 75a597759..1b7600126 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -80,6 +80,7 @@ Track::Track(std::string filename) m_sky_particles_emitter = NULL; m_sky_dx = 0.05f; m_sky_dy = 0.0f; + m_weather_type = WEATHER_NONE; loadTrackInfo(); } // Track @@ -880,16 +881,26 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id) } else if(name=="weather") { - std::string sky_particles; - node->get("particles", &sky_particles); - if (sky_particles.size() ==0) + std::string weather_particles; + std::string weather_type; + node->get("particles", &weather_particles); + node->get("type", &weather_type); + + if (weather_particles.size() > 0) + { + m_sky_particles = + ParticleKindManager::get()->getParticles(weather_particles); + } + else if (weather_type.size() > 0) + { + m_weather_type = WEATHER_RAIN; + } + else { fprintf(stderr, - "Warning: no weather particles found - ignored.\n"); + "Warning: bas weather node found - ignored.\n"); continue; } - m_sky_particles = - ParticleKindManager::get()->getParticles(sky_particles); } else { diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 48d561d20..80ab3d201 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -48,6 +48,12 @@ class TriangleMesh; class World; class XMLNode; +enum WeatherType +{ + WEATHER_NONE, + WEATHER_RAIN +}; + /** * \ingroup tracks */ @@ -125,9 +131,12 @@ private: /** If a sky dome is used, percentage of the texture to be used. */ float m_sky_texture_percent; - /** Particles emitted from the sky (e.g. rain or snow) */ + /** Particles emitted from the sky (wheather) */ ParticleKind* m_sky_particles; + /** Use a special built-in wheather */ + WeatherType m_weather_type; + ParticleEmitter* m_sky_particles_emitter; /** A simple class to keep information about a track mode. */ @@ -297,6 +306,9 @@ public: /** Get the number of start positions defined in the scene file. */ unsigned int getNumberOfStartPositions() const { return m_start_transforms.size(); } + + WeatherType getWeatherType () const { return m_weather_type; } + }; // class Track #endif