Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color tinting for mesh markers #752

Merged
merged 1 commit into from
Apr 30, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 63 additions & 49 deletions src/rviz/default_plugin/markers/mesh_resource_marker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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();

Expand All @@ -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());
}
Expand All @@ -120,84 +124,95 @@ 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);
}
}

// make sub-entities use cloned materials
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
{
// BaseWhiteNoLighting is the default material Ogre uses
// 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;
Expand All @@ -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<Ogre::Pass*>::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);
}
}

Expand All @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/rviz/default_plugin/markers/mesh_resource_marker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Ogre::Pass*> color_tint_passes_;
};

}
Expand Down