diff --git a/src/rviz/default_plugin/markers/mesh_resource_marker.cpp b/src/rviz/default_plugin/markers/mesh_resource_marker.cpp index 616f0f4000..1759f09c04 100644 --- a/src/rviz/default_plugin/markers/mesh_resource_marker.cpp +++ b/src/rviz/default_plugin/markers/mesh_resource_marker.cpp @@ -65,13 +65,14 @@ void MeshResourceMarker::reset() //destroy entity if (entity_) { - context_->getSceneManager()->destroyEntity( entity_ ); + context_->getSceneManager()->destroyEntity(entity_); entity_ = 0; } + // destroy all the materials we've created S_MaterialPtr::iterator it; - for ( it = materials_.begin(); it!=materials_.end(); it++ ) + for (it = materials_.begin(); it != materials_.end(); it++) { Ogre::MaterialPtr material = *it; if (!material.isNull()) @@ -81,19 +82,22 @@ void MeshResourceMarker::reset() } } materials_.clear(); + // the actual passes are deleted by the material + color_tint_passes_.clear(); } void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const MarkerConstPtr& new_message) { ROS_ASSERT(new_message->type == visualization_msgs::Marker::MESH_RESOURCE); - bool need_color = false; + // flag indicating if the mesh material color needs to be updated + bool update_color = false; scene_node_->setVisible(false); - if( !entity_ || + if (!entity_ || old_message->mesh_resource != new_message->mesh_resource || - old_message->mesh_use_embedded_materials != new_message->mesh_use_embedded_materials ) + old_message->mesh_use_embedded_materials != new_message->mesh_use_embedded_materials) { reset(); @@ -106,7 +110,7 @@ void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const M { std::stringstream ss; ss << "Mesh resource marker [" << getStringID() << "] could not load [" << new_message->mesh_resource << "]"; - if ( owner_ ) + if (owner_) { owner_->setMarkerStatus(getID(), StatusProperty::Error, ss.str()); } @@ -120,28 +124,27 @@ void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const M std::string id = ss.str(); entity_ = context_->getSceneManager()->createEntity(id, new_message->mesh_resource); scene_node_->attachObject(entity_); - need_color = true; // create a default material for any sub-entities which don't have their own. ss << "Material"; - Ogre::MaterialPtr default_material = Ogre::MaterialManager::getSingleton().create( ss.str(), ROS_PACKAGE_NAME ); + Ogre::MaterialPtr default_material = Ogre::MaterialManager::getSingleton().create(ss.str(), ROS_PACKAGE_NAME); default_material->setReceiveShadows(false); default_material->getTechnique(0)->setLightingEnabled(true); - default_material->getTechnique(0)->setAmbient( 0.5, 0.5, 0.5 ); - materials_.insert( default_material ); + default_material->getTechnique(0)->setAmbient(0.5, 0.5, 0.5); + materials_.insert(default_material); - if ( new_message->mesh_use_embedded_materials ) + if (new_message->mesh_use_embedded_materials) { // make clones of all embedded materials so selection works correctly S_MaterialPtr materials = getMaterials(); S_MaterialPtr::iterator it; - for ( it = materials.begin(); it!=materials.end(); it++ ) + for (it = materials.begin(); it != materials.end(); it++) { - if( (*it)->getName() != "BaseWhiteNoLighting" ) + if ((*it)->getName() != "BaseWhiteNoLighting") { - Ogre::MaterialPtr new_material = (*it)->clone( id + (*it)->getName() ); - materials_.insert( new_material ); + Ogre::MaterialPtr new_material = (*it)->clone(id + (*it)->getName()); + materials_.insert(new_material); } } @@ -149,9 +152,9 @@ void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const M for (uint32_t i = 0; i < entity_->getNumSubEntities(); ++i) { std::string mat_name = entity_->getSubEntity(i)->getMaterialName(); - if( mat_name != "BaseWhiteNoLighting" ) + if (mat_name != "BaseWhiteNoLighting") { - entity_->getSubEntity(i)->setMaterialName( id + mat_name ); + entity_->getSubEntity(i)->setMaterialName(id + mat_name); } else { @@ -159,45 +162,57 @@ void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const M // when it sees a mesh with no material. Here we replace // that with our default_material which gets colored with // new_message->color. - entity_->getSubEntity(i)->setMaterial( default_material ); + entity_->getSubEntity(i)->setMaterial(default_material); } } } else { - entity_->setMaterial( default_material ); + entity_->setMaterial(default_material); + } + + // add a pass to every material to perform the color tinting + S_MaterialPtr::iterator material_it; + for (material_it = materials_.begin(); material_it != materials_.end(); material_it++) + { + Ogre::Technique* technique = (*material_it)->getTechnique(0); + color_tint_passes_.push_back(technique->createPass()); } - handler_.reset( new MarkerSelectionHandler( this, MarkerID( new_message->ns, new_message->id ), context_ )); - handler_->addTrackedObject( entity_ ); + // always update color on resource change + update_color = true; + + handler_.reset(new MarkerSelectionHandler(this, MarkerID(new_message->ns, new_message->id), context_)); + handler_->addTrackedObject(entity_); + } + else + { + // underlying mesh resource has not changed but if the color has + // then we need to update the materials color + if (!old_message + || old_message->color.r != new_message->color.r + || old_message->color.g != new_message->color.g + || old_message->color.b != new_message->color.b + || old_message->color.a != new_message->color.a) + { + update_color = true; + } } - if( need_color || - old_message->color.r != new_message->color.r || - old_message->color.g != new_message->color.g || - old_message->color.b != new_message->color.b || - old_message->color.a != new_message->color.a ) + // update material color + // if the mesh_use_embedded_materials is true and color is non-zero + // then the color will be used to tint the embedded materials + if (update_color) { float r = new_message->color.r; float g = new_message->color.g; float b = new_message->color.b; float a = new_message->color.a; - // Old way was to ignore the color and alpha when using embedded - // materials, which meant you could leave them unset, which means - // 0. Since we now USE the color and alpha values, leaving them - // all 0 will mean the object will be invisible. Therefore detect - // the situation where RGBA are all 0 and treat that the same as - // all 1 (full white). - if( new_message->mesh_use_embedded_materials && r == 0 && g == 0 && b == 0 && a == 0 ) - { - r = 1; g = 1; b = 1; a = 1; - } - Ogre::SceneBlendType blending; bool depth_write; - if ( a < 0.9998 ) + if (a < 0.9998) { blending = Ogre::SBT_TRANSPARENT_ALPHA; depth_write = false; @@ -208,16 +223,15 @@ void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const M depth_write = true; } - S_MaterialPtr::iterator it; - for( it = materials_.begin(); it != materials_.end(); it++ ) + for (std::vector::iterator it = color_tint_passes_.begin(); + it != color_tint_passes_.end(); + ++it) { - Ogre::Technique* technique = (*it)->getTechnique( 0 ); - - technique->setAmbient( r*0.5, g*0.5, b*0.5 ); - technique->setDiffuse( r, g, b, a ); - technique->setSceneBlending( blending ); - technique->setDepthWriteEnabled( depth_write ); - technique->setLightingEnabled( true ); + (*it)->setAmbient(0.5 * r, 0.5 * g, 0.5 * b); + (*it)->setDiffuse(r, g, b, a); + (*it)->setSceneBlending(blending); + (*it)->setDepthWriteEnabled(depth_write); + (*it)->setLightingEnabled(true); } } @@ -235,9 +249,9 @@ void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const M S_MaterialPtr MeshResourceMarker::getMaterials() { S_MaterialPtr materials; - if( entity_ ) + if (entity_) { - extractMaterials( entity_, materials ); + extractMaterials(entity_, materials); } return materials; } diff --git a/src/rviz/default_plugin/markers/mesh_resource_marker.h b/src/rviz/default_plugin/markers/mesh_resource_marker.h index 683a97da2c..67b8d16dd4 100644 --- a/src/rviz/default_plugin/markers/mesh_resource_marker.h +++ b/src/rviz/default_plugin/markers/mesh_resource_marker.h @@ -64,6 +64,8 @@ class MeshResourceMarker : public MarkerBase //! Scaling factor to convert units. Currently relevant for Collada only. float unit_rescale_; + //! list of passes created for adding color tint to the mesh + std::vector color_tint_passes_; }; }