diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index fc2c3737916..98a4d705bff 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -143,6 +143,7 @@ Material::Material(const XMLNode *node, bool deprecated) node->get("disable-z-write", &m_disable_z_write ); node->get("colorizable", &m_colorizable ); node->get("colorization-factor", &m_colorization_factor); + node->get("hue-settings", &m_hue_settings ); node->get("fog", &m_fog ); node->get("mask", &m_mask ); diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index d5cc5c39d26..910e60c1265 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -21,6 +21,7 @@ #define HEADER_MATERIAL_HPP #include "utils/no_copy.hpp" +#include "utils/random_generator.hpp" #include #include @@ -181,6 +182,12 @@ class Material : public NoCopy /** Minimum resulting saturation when colorized (from 0 to 1) */ float m_colorization_factor; + /** List of hue pre-defined for colorization (from 0 to 1) */ + std::vector m_hue_settings; + + /** Random generator for getting pre-defined hue */ + RandomGenerator m_random_hue; + /** Some textures need to be pre-multiplied, some divided to give * the intended effect. */ //enum {ADJ_NONE, ADJ_PREMUL, ADJ_DIV} @@ -291,7 +298,7 @@ class Material : public NoCopy * is driving on it. */ bool isDriveReset () const { return m_drive_reset; } // ------------------------------------------------------------------------ - /** Returns if this material can be colorized (like red/blue in team game). + /** Returns if this material can be colorized. */ bool isColorizable () const { return m_colorizable; } // ------------------------------------------------------------------------ @@ -299,6 +306,17 @@ class Material : public NoCopy */ float getColorizationFactor () const { return m_colorization_factor; } // ------------------------------------------------------------------------ + /** Returns a random hue when colorized. + */ + float getRandomHue() + { + if (m_hue_settings.empty()) + return 0.0f; + const unsigned int hue = m_random_hue.get(m_hue_settings.size()); + assert(hue < m_hue_settings.size()); + return m_hue_settings[hue]; + } + // ------------------------------------------------------------------------ /** Returns if this material should trigger a rescue if a kart * crashes against it. */ CollisionReaction getCollisionReaction() const { return m_collision_reaction; } diff --git a/src/graphics/render_info.cpp b/src/graphics/render_info.cpp index b3276b89169..46555d787fe 100644 --- a/src/graphics/render_info.cpp +++ b/src/graphics/render_info.cpp @@ -26,6 +26,19 @@ // ---------------------------------------------------------------------------- RenderInfo::RenderInfo(float hue, bool transparent) { - m_hue = hue; + m_static_hue = hue; m_transparent = transparent; } // RenderInfo + +// ---------------------------------------------------------------------------- +void RenderInfo::setDynamicHue(irr::scene::IMesh* mesh) +{ + unsigned int n = mesh->getMeshBufferCount(); + for (unsigned int i = 0; i < n; i++) + { + scene::IMeshBuffer *mb = mesh->getMeshBuffer(i); + Material* m = material_manager->getMaterialFor(mb + ->getMaterial().getTexture(0), mb); + m_dynamic_hue.push_back(m->getRandomHue()); + } +} // setDynamicHue diff --git a/src/graphics/render_info.hpp b/src/graphics/render_info.hpp index a7e5518e82d..94c8a18dcf2 100644 --- a/src/graphics/render_info.hpp +++ b/src/graphics/render_info.hpp @@ -21,6 +21,8 @@ #include "utils/leak_check.hpp" +#include + namespace irr { namespace scene { class IMesh; } @@ -41,10 +43,12 @@ class RenderInfo }; private: - float m_hue; + float m_static_hue; bool m_transparent; + std::vector m_dynamic_hue; + public: LEAK_CHECK(); // ------------------------------------------------------------------------ @@ -52,11 +56,11 @@ class RenderInfo // ------------------------------------------------------------------------ ~RenderInfo() {} // ------------------------------------------------------------------------ - void setHue(float hue) { m_hue = hue; } + void setHue(float hue) { m_static_hue = hue; } // ------------------------------------------------------------------------ void setTransparent(bool transparent) { m_transparent = transparent; } // ------------------------------------------------------------------------ - float getHue() const { return m_hue; } + float getHue() const { return m_static_hue; } // ------------------------------------------------------------------------ bool isTransparent() const { return m_transparent; } // ------------------------------------------------------------------------ @@ -68,7 +72,20 @@ class RenderInfo setTransparent(krt == RenderInfo::KRT_TRANSPARENT ? true : false); } // ------------------------------------------------------------------------ - void setRenderInfo(const RenderInfo* other) { *this = *other; } + /** Returns true if this render info is static. ie affect all material + * using the same hue. (like the kart colorization in soccer game) + */ + bool isStatic() const { return m_dynamic_hue.empty(); } + // ------------------------------------------------------------------------ + unsigned int getNumberOfHue() const { return m_dynamic_hue.size(); } + // ------------------------------------------------------------------------ + float getDynamicHue(unsigned int hue) const + { + assert(hue < m_dynamic_hue.size()); + return m_dynamic_hue[hue]; + } + // ------------------------------------------------------------------------ + void setDynamicHue(irr::scene::IMesh* mesh); }; // RenderInfo diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index bd216f6bae4..949f4e7e465 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -100,22 +100,44 @@ void STKAnimatedMesh::updateNoGL() if (!isMaterialInitialized) { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - for (u32 i = 0; i < m->getMeshBufferCount(); ++i) + const u32 mb_count = m->getMeshBufferCount(); + for (u32 i = 0; i < mb_count; ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); bool affected = false; - if (!m_all_parts_colorized && mb && m_mesh_render_info) + RenderInfo* cur_ri = m_mesh_render_info; + if (!m_all_parts_colorized && mb && cur_ri) { - // Test if material is affected by hue change - Material* m = material_manager->getMaterialFor(mb - ->getMaterial().getTexture(0), mb); - if (m->isColorizable()) - affected = true; + if (m_mesh_render_info && !m_mesh_render_info->isStatic()) + { + // Convert to static render info for each mesh buffer + assert(m_mesh_render_info->getNumberOfHue() == mb_count); + const float hue = m_mesh_render_info->getDynamicHue(i); + if (hue > 0.0f) + { + cur_ri = new RenderInfo(hue); + m_static_render_info.push_back(cur_ri); + affected = true; + } + else + { + cur_ri = NULL; + } + } + else + { + // Test if material is affected by static hue change + Material* m = material_manager->getMaterialFor(mb + ->getMaterial().getTexture(0), mb); + if (m->isColorizable()) + affected = true; + } } + assert(cur_ri ? cur_ri->isStatic() : true); GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name, - affected || m_all_parts_colorized || (m_mesh_render_info - && m_mesh_render_info->isTransparent()) ? m_mesh_render_info : NULL)); + affected || m_all_parts_colorized || (cur_ri + && cur_ri->isTransparent()) ? cur_ri : NULL)); } for (u32 i = 0; i < m->getMeshBufferCount(); ++i) diff --git a/src/graphics/stk_animated_mesh.hpp b/src/graphics/stk_animated_mesh.hpp index 70462689aa5..f7c10019e4d 100644 --- a/src/graphics/stk_animated_mesh.hpp +++ b/src/graphics/stk_animated_mesh.hpp @@ -32,6 +32,7 @@ class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMes protected: bool isMaterialInitialized; bool isGLInitialized; + PtrVector m_static_render_info; std::vector GLmeshes; core::matrix4 ModelViewProjectionMatrix; void cleanGLMeshes(); diff --git a/src/graphics/stk_mesh_scene_node.cpp b/src/graphics/stk_mesh_scene_node.cpp index 0b5f651dc72..3249aa1f7f8 100644 --- a/src/graphics/stk_mesh_scene_node.cpp +++ b/src/graphics/stk_mesh_scene_node.cpp @@ -77,22 +77,44 @@ void STKMeshSceneNode::setReloadEachFrame(bool val) void STKMeshSceneNode::createGLMeshes(RenderInfo* render_info, bool all_parts_colorized) { - for (u32 i = 0; igetMeshBufferCount(); ++i) + const u32 mb_count = Mesh->getMeshBufferCount(); + for (u32 i = 0; i < mb_count; ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); bool affected = false; + RenderInfo* cur_ri = render_info; if (!all_parts_colorized && mb && render_info) { - // Test if material is affected by hue change - Material* m = material_manager->getMaterialFor(mb - ->getMaterial().getTexture(0), mb); - if (m->isColorizable()) - affected = true; + if (render_info && !render_info->isStatic()) + { + // Convert to static render info for each mesh buffer + assert(render_info->getNumberOfHue() == mb_count); + const float hue = render_info->getDynamicHue(i); + if (hue > 0.0f) + { + cur_ri = new RenderInfo(hue); + m_static_render_info.push_back(cur_ri); + affected = true; + } + else + { + cur_ri = NULL; + } + } + else + { + // Test if material is affected by static hue change + Material* m = material_manager->getMaterialFor(mb + ->getMaterial().getTexture(0), mb); + if (m->isColorizable()) + affected = true; + } } + assert(cur_ri ? cur_ri->isStatic() : true); GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name, - affected || all_parts_colorized || (render_info && - render_info->isTransparent()) ? render_info : NULL)); + affected || all_parts_colorized || (cur_ri && + cur_ri->isTransparent()) ? cur_ri : NULL)); } isMaterialInitialized = false; isGLInitialized = false; diff --git a/src/graphics/stk_mesh_scene_node.hpp b/src/graphics/stk_mesh_scene_node.hpp index 7d9f034ad53..ae879e7b606 100644 --- a/src/graphics/stk_mesh_scene_node.hpp +++ b/src/graphics/stk_mesh_scene_node.hpp @@ -28,6 +28,7 @@ class RenderInfo; class STKMeshSceneNode : public irr::scene::CMeshSceneNode, public STKMeshCommon { protected: + PtrVector m_static_render_info; std::vector GLmeshes; core::matrix4 ModelViewProjectionMatrix; core::vector3df windDir; diff --git a/src/scriptengine/script_challenges.cpp b/src/scriptengine/script_challenges.cpp index ae8ff248ff0..2dd100f1208 100644 --- a/src/scriptengine/script_challenges.cpp +++ b/src/scriptengine/script_challenges.cpp @@ -23,7 +23,6 @@ #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" #include "guiengine/engine.hpp" -#include "guiengine/scalable_font.hpp" #include "modes/world.hpp" #include "config/player_manager.hpp" #include "states_screens/dialogs/tutorial_message_dialog.hpp" diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index b4715f6ab13..cadd52249b7 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -38,8 +38,6 @@ #include "graphics/particle_emitter.hpp" #include "graphics/particle_kind.hpp" #include "graphics/particle_kind_manager.hpp" -#include "graphics/render_info.hpp" -#include "guiengine/scalable_font.hpp" #include "io/file_manager.hpp" #include "io/xml_node.hpp" #include "items/item.hpp" @@ -1739,7 +1737,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) } } - loadObjects(root, path, model_def_loader, true, NULL, NULL, NULL); + loadObjects(root, path, model_def_loader, true, NULL, NULL); model_def_loader.cleanLibraryNodesAfterLoad(); @@ -1929,7 +1927,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& model_def_loader, bool create_lod_definitions, scene::ISceneNode* parent, - TrackObject* parent_library, RenderInfo* ri) + TrackObject* parent_library) { unsigned int start_position_counter = 0; @@ -1943,7 +1941,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin if (name == "track" || name == "default-start") continue; if (name == "object" || name == "library") { - m_track_object_manager->add(*node, parent, model_def_loader, parent_library, ri); + m_track_object_manager->add(*node, parent, model_def_loader, parent_library); } else if (name == "water") { @@ -1987,7 +1985,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin { if (UserConfigParams::m_graphical_effects) { - m_track_object_manager->add(*node, parent, model_def_loader, parent_library, NULL); + m_track_object_manager->add(*node, parent, model_def_loader, parent_library); } } else if (name == "sky-dome" || name == "sky-box" || name == "sky-color") @@ -2000,7 +1998,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin } else if (name == "light") { - m_track_object_manager->add(*node, parent, model_def_loader, parent_library, NULL); + m_track_object_manager->add(*node, parent, model_def_loader, parent_library); } else if (name == "weather") { diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 7308a68669a..185bdd759b2 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -56,7 +56,6 @@ class MusicInformation; class ParticleEmitter; class ParticleKind; class PhysicalObject; -class RenderInfo; class TrackObject; class TrackObjectManager; class TriangleMesh; @@ -457,8 +456,7 @@ class Track // ------------------------------------------------------------------------ void loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& lod_loader, bool create_lod_definitions, - scene::ISceneNode* parent, TrackObject* parent_library, - RenderInfo* ri); + scene::ISceneNode* parent, TrackObject* parent_library); // ------------------------------------------------------------------------ bool isSoccer () const { return m_is_soccer; } // ------------------------------------------------------------------------ diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index ac9e9533749..c8db09632e4 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -20,6 +20,8 @@ #include "animations/three_d_animation.hpp" #include "graphics/irr_driver.hpp" +#include "graphics/material.hpp" +#include "graphics/material_manager.hpp" #include "graphics/render_info.hpp" #include "io/file_manager.hpp" #include "io/xml_node.hpp" @@ -43,9 +45,9 @@ */ TrackObject::TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader, - TrackObject* parent_library, RenderInfo* ri) + TrackObject* parent_library) { - init(xml_node, parent, model_def_loader, parent_library, ri); + init(xml_node, parent, model_def_loader, parent_library); } // TrackObject // ---------------------------------------------------------------------------- @@ -68,6 +70,7 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr, m_animator = NULL; m_physical_object = NULL; m_parent_library = NULL; + m_render_info = NULL; m_interaction = interaction; m_presentation = presentation; m_is_driveable = false; @@ -94,11 +97,12 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr, */ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader, - TrackObject* parent_library, RenderInfo* ri) + TrackObject* parent_library) { m_init_xyz = core::vector3df(0,0,0); m_init_hpr = core::vector3df(0,0,0); m_init_scale = core::vector3df(1,1,1); + m_render_info = NULL; m_enabled = true; m_initially_visible = false; m_presentation = NULL; @@ -178,13 +182,35 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, } else { + // Colorization settings + std::string model_name; + xml_node.get("model", &model_name); + scene::IMesh* mesh = irr_driver->getMesh(model_name); + + bool colorizable = false; + unsigned int n = mesh->getMeshBufferCount(); + for (unsigned int i = 0; i < n; i++) + { + scene::IMeshBuffer *mb = mesh->getMeshBuffer(i); + Material* m = material_manager->getMaterialFor(mb + ->getMaterial().getTexture(0), mb); + colorizable = colorizable || m->isColorizable(); + } + + // If at least one material is colorizable, add RenderInfo for it + if (colorizable) + { + m_render_info = new RenderInfo(); + m_render_info->setDynamicHue(mesh); + } + scene::ISceneNode *glownode = NULL; bool is_movable = false; if (lod_instance) { m_type = "lod"; TrackObjectPresentationLOD* lod_node = - new TrackObjectPresentationLOD(xml_node, parent, model_def_loader, ri); + new TrackObjectPresentationLOD(xml_node, parent, model_def_loader, m_render_info); m_presentation = lod_node; LODNode* node = (LODNode*)lod_node->getNode(); @@ -209,7 +235,7 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, m_presentation = new TrackObjectPresentationMesh(xml_node, m_enabled, parent, - ri); + m_render_info); scene::ISceneNode* node = ((TrackObjectPresentationMesh *)m_presentation)->getNode(); if (type == "movable" && parent != NULL) { @@ -356,6 +382,7 @@ TrackObject::~TrackObject() delete m_presentation; delete m_animator; delete m_physical_object; + delete m_render_info; } // ~TrackObject // ---------------------------------------------------------------------------- diff --git a/src/tracks/track_object.hpp b/src/tracks/track_object.hpp index fc53c6e5c37..ceabc0c3154 100644 --- a/src/tracks/track_object.hpp +++ b/src/tracks/track_object.hpp @@ -31,10 +31,10 @@ #include #include "animations/three_d_animation.hpp" -class XMLNode; -class ThreeDAnimation; class ModelDefinitionLoader; class RenderInfo; +class ThreeDAnimation; +class XMLNode; /** * \ingroup tracks @@ -60,8 +60,9 @@ class TrackObject : public NoCopy std::string m_id; -protected: + RenderInfo* m_render_info; +protected: /** The initial XYZ position of the object. */ core::vector3df m_init_xyz; @@ -99,14 +100,13 @@ class TrackObject : public NoCopy void init(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader, - TrackObject* parent_library, RenderInfo* ri); + TrackObject* parent_library); public: TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader, - TrackObject* parent_library, - RenderInfo* ri); + TrackObject* parent_library); TrackObject(const core::vector3df& xyz, const core::vector3df& hpr, diff --git a/src/tracks/track_object_manager.cpp b/src/tracks/track_object_manager.cpp index 30fd88d96b7..b1afb604559 100644 --- a/src/tracks/track_object_manager.cpp +++ b/src/tracks/track_object_manager.cpp @@ -22,7 +22,6 @@ #include "animations/three_d_animation.hpp" #include "graphics/lod_node.hpp" #include "graphics/material_manager.hpp" -#include "graphics/render_info.hpp" #include "io/xml_node.hpp" #include "physics/physical_object.hpp" #include "tracks/track_object.hpp" @@ -46,11 +45,11 @@ TrackObjectManager::~TrackObjectManager() */ void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader, - TrackObject* parent_library, RenderInfo* ri) + TrackObject* parent_library) { try { - TrackObject *obj = new TrackObject(xml_node, parent, model_def_loader, parent_library, ri); + TrackObject *obj = new TrackObject(xml_node, parent, model_def_loader, parent_library); m_all_objects.push_back(obj); if(obj->isDriveable()) m_driveable_objects.push_back(obj); diff --git a/src/tracks/track_object_manager.hpp b/src/tracks/track_object_manager.hpp index 3f62ec9fb50..24cc1755777 100644 --- a/src/tracks/track_object_manager.hpp +++ b/src/tracks/track_object_manager.hpp @@ -23,11 +23,10 @@ #include "tracks/track_object.hpp" #include "utils/ptr_vector.hpp" -class LODNode; -class RenderInfo; class Track; class Vec3; class XMLNode; +class LODNode; #include #include @@ -59,7 +58,7 @@ class TrackObjectManager void init(); void add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader, - TrackObject* parent_library, RenderInfo* ri); + TrackObject* parent_library); void update(float dt); void handleExplosion(const Vec3 &pos, const PhysicalObject *mp, bool secondary_hits=true); diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp index f53c93ef58e..783ba803f54 100644 --- a/src/tracks/track_object_presentation.cpp +++ b/src/tracks/track_object_presentation.cpp @@ -177,13 +177,8 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode( ModelDefinitionLoader& model_def_loader) : TrackObjectPresentationSceneNode(xml_node) { - m_render_info = NULL; std::string name; xml_node.get("name", &name); - float custom_hue = 0.0f; - xml_node.get("hue", &custom_hue); - if (custom_hue > 0.0f) - m_render_info = new RenderInfo(custom_hue, false); m_node = irr_driver->getSceneManager()->addEmptySceneNode(); #ifdef DEBUG @@ -273,7 +268,7 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode( assert(libroot != NULL); World::getWorld()->getTrack()->loadObjects(libroot, lib_path, model_def_loader, - create_lod_definitions, m_node, parent, m_render_info); + create_lod_definitions, m_node, parent); m_parent = parent; } // TrackObjectPresentationLibraryNode @@ -281,8 +276,6 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode( TrackObjectPresentationLibraryNode::~TrackObjectPresentationLibraryNode() { irr_driver->removeNode(m_node); - delete m_render_info; - m_render_info = NULL; } // TrackObjectPresentationLibraryNode // ---------------------------------------------------------------------------- void TrackObjectPresentationLibraryNode::move(const core::vector3df& xyz, const core::vector3df& hpr, diff --git a/src/tracks/track_object_presentation.hpp b/src/tracks/track_object_presentation.hpp index 37f08f9a44b..a92d62cfd53 100644 --- a/src/tracks/track_object_presentation.hpp +++ b/src/tracks/track_object_presentation.hpp @@ -185,7 +185,6 @@ class TrackObjectPresentationEmpty : public TrackObjectPresentationSceneNode class TrackObjectPresentationLibraryNode : public TrackObjectPresentationSceneNode { TrackObject* m_parent; - RenderInfo* m_render_info; public: TrackObjectPresentationLibraryNode(TrackObject* parent, const XMLNode& xml_node,