Hey all! I have a simple program that loads in a 3D model and then uses
a node visitor to print out some data about the model. One piece of
data that the node visitor is printing is the model's texture filename.
The code from the node visitor to do this appears as follows:
/***************[Begin Code]***************************/
// The apply(osg::Geode) function looks through the drawables in the
geode and calls this apply function
// for the osg::StateSet of each drawable found.
void TextureChangeVisitor::apply(osg::StateSet* stateset)
{
if (stateset)
{
for(unsigned int
i=0;i<stateset->getTextureAttributeList().size();++i)
{
osg::Texture2D* texture =
dynamic_cast<osg::Texture2D*>(stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
if (texture)
{
if(texture->getImage())
std::cout << "-Texture File: " <<
texture->getImage()->getFileName() << std::endl;
else
std::cout << "Error, Invalid Image!" << std::endl;
}
}
}
}
/***************[End Code]***************************/
If I use this node visitor to traverse my model anywhere in my program
after my call to osgDB::readNodeFile(), the texture filename is printed
out as normal. If I pass the model to my keyboard handler though, and
try to traverse with my node visitor each time a key is pressed, it will
not be able to get a valid image from the texture (so the program prints
the "Error, Invalid Image!" line from the above function).
Here is the code for the rest of the program. The keyboard handler, the
model loading function, and the main. Does anyone have any idea why I
the above code doesn't work when executed from inside the
KeyboardEventHandler class?
/***************[Begin Code]***************************/
///
// class KeyboardEventHandler
///
/// Handle keyboard input from the user
///
/// This class is able to read keyboard input.
/// In this program, it is merely used to check
/// for any key being pressed. If a key is
/// pressed, we will attempt to toggle our model
/// texture
///
class KeyboardEventHandler : public osgGA::GUIEventHandler
{
public:
KeyboardEventHandler(osg::ref_ptr<osg::Node>& input_model):
model(input_model)
{
}
virtual bool handle(const osgGA::GUIEventAdapter&
ea,osgGA::GUIActionAdapter&)
{
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYUP):
{
// Using the node visitor to traverse here does not
work!
TextureChangeVisitor tex_nv;
model->asGroup()->traverse(tex_nv);
return true;
}
default:
{
return false;
}
}
}
virtual void accept(osgGA::GUIEventHandlerVisitor& v)
{
v.visit(*this);
}
private:
osg::ref_ptr<osg::Node>& model;
};
///
// LoadModel
///
/// Load in a 3D model (of any file type compatible with OpenSceneGraph).
///
/// This function uses the built in OSG model loader
/// function to open a file. This function will open
/// any model type that OSG can normally load (and any
/// others that the user has the appropriate plugin for).
///
osg::Node* LoadModel(const std::string modelFile)
{
// Read in the model file
osg::Node* model = osgDB::readNodeFile("Models/Plane/Hat_01.3DS");
// If the model failed to load...
if(!model)
{
// ... generate an error and exit the program
std::cout << "Program failed to load " << modelFile << std::endl;
exit(1);
}
// Create a new optimizer to optimize the model
osgUtil::Optimizer optimizer;
optimizer.optimize(model);
// The traversal works just fine here!
TextureChangeVisitor tex_nv;
model->asGroup()->traverse(tex_nv);
// return our loaded model
return(model);
}
///
// main
///
/// The main function of the TextureChanger project.
///
/// This is our program entry point. The main function
/// does all the command line parsing for the program.
/// It also uses the LoadModel function to load in a 3D
/// model.
///
int main (int argc, char** argv)
{
// Create a standard Producer-based viewer
osgProducer::Viewer viewer;
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
// Reference counted model
osg::ref_ptr<osg::Node> model;
// Load in the model
model = LoadModel("");
KeyboardEventHandler* keh = new KeyboardEventHandler(model);
viewer.getEventHandlerList().push_front(keh);
// add model to the viewer to be drawn
viewer.setSceneData( model.get() );
// Enter rendering loop
viewer.realize();
while (!viewer.done())
{
// wait for all cull and draw threads to complete.
viewer.sync();
// update the scene by traversing it with the the update
visitor which will
// call all node update callbacks and animations.
viewer.update();
// fire off the cull and draw traversals of the scene.
viewer.frame();
}
// Wait for all cull and draw threads to complete before exit.
viewer.sync();
}
/***************[End Code]***************************/
Finally, here is some sample output to show exactly what is going wrong:
-GEODE
-There is/are 1 drawables in this geode:
-Drawable #0
-Vertex Array contains 1209 vertices
-The array is of type: 10
-Texture Coordinate Array contains 1209 texture points
-The array is of type: 9
-Texture File: Models/Plane/Hat_01.tga <---[ This is what
should happen]
-Values are stored as triangles
-There are 1833 indices
-The max index value is: 1208
-The min index value is: 0
-GEODE
-There is/are 1 drawables in this geode:
-Drawable #0
-Vertex Array contains 1209 vertices
-The array is of type: 10
-Texture Coordinate Array contains 1209 texture points
-The array is of type: 9
Error, Invalid Image! <---[ when called from the KeyboardEventHandler]
-Values are stored as triangles
-There are 1833 indices
-The max index value is: 1208
-The min index value is: 0
-GEODE
-There is/are 1 drawables in this geode:
-Drawable #0
-Vertex Array contains 1209 vertices
-The array is of type: 10
-Texture Coordinate Array contains 1209 texture points
-The array is of type: 9
Error, Invalid Image! <---[ when called from the KeyboardEventHandler]
-Values are stored as triangles
-There are 1833 indices
-The max index value is: 1208
-The min index value is: 0
Thanks in advance for any help anyone can offer!
-Mark Waligora
_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/