Re: [osg-users] Update node color on demand
Hi, try in void ColorVisitor::apply(osg::Geode &geode) { . if (colorArrays) { for (unsigned int i = 0; i < colorArrays->size(); i++) { osg::Vec4 *color = &colorArrays->operator [](i); // // could also use *color = m_color // color->set(m_color._v[0], m_color._v[1], m_color._v[2], m_color._v[3]); } colorArrays->dirty() or ->dirtyBufferObject() I am not sure what was the right call. Please look it up. It is not enough only to change the color, you have to dirty the array to be updated } On Tue, Nov 27, 2018 at 2:10 AM Diego Mancilla wrote: > Hello Trajce, > > The visitor class implementation is on my previous post on this thread. I > took that code from Gordon Tomlison's OSG Samples, and it works when is > used previous to the rendering as you can see on my initial post (other > thread: http://forum.openscenegraph.org/viewtopic.php?p=75209#75209). > > > As I said everything gets called when it should, but on runtime, the > lines wont change color. I you look at the code snippet of my main: > > > > Code: > _lines = osgDB::readNodeFile("lines.dxf"); > _topo->setDataVariance(osg::Object::DYNAMIC); > osg::Geode* geode = new osg::Geode; > > _mViewer->addEventHandler(new ColorHandler); > > ColorVisitor newColor; > newColor.setColor( 1.0f, 0.0f, 0.0f ); > _lines->accept(newColor); > geode->addChild(_lines); > _mViewer->realize(); > > > > The color of the lines turns red on start. But then, when I try to change > it to another color on runetime, nothing happens. > > Anyway, here is the visitor implementation (.cpp): > > > Code: > ColorVisitor::ColorVisitor(): > osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) > { > m_color.set(1.0, 1.0, 1.0, 1.0); > m_colorArrays = new osg::Vec4Array; > m_colorArrays->push_back(m_color); > }; > > ColorVisitor::ColorVisitor(const osg::Vec4 &color): > osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) > { > m_color = color; > m_colorArrays = new osg::Vec4Array; > m_colorArrays->push_back(m_color); > > }; > > ColorVisitor::~ColorVisitor() > { > }; > > void ColorVisitor::apply(osg::Node &node) { > // > // > // Handle traversal of osg::Node node types > // > // > traverse(node); > }; > > void ColorVisitor::apply(osg::Geode &geode) { > // > // > // Handle traversal of osg::Geode node types > // > // > > osg::StateSet *state = NULL; > unsigned intvertNum = 0; > // > // We need to iterate through all the drawables check if > // the contain any geometry that we will need to process > // > > unsigned int numGeoms = geode.getNumDrawables(); > > for (unsigned int geodeIdx = 0; geodeIdx < numGeoms; geodeIdx++) > { > // > // Use 'asGeometry' as its supposed to be faster than a > dynamic_cast > // every little saving counts > // > osg::Geometry *curGeom = > geode.getDrawable(geodeIdx)->asGeometry(); > // > // Only process if the drawable is geometry > // > if (curGeom) > { > osg::Vec4Array *colorArrays = dynamic_cast *>(curGeom->getColorArray()); > if (colorArrays) { > for (unsigned int i = 0; i < colorArrays->size(); i++) > { > osg::Vec4 *color = &colorArrays->operator [](i); > // > // could also use *color = m_color > // > color->set(m_color._v[0], m_color._v[1], > m_color._v[2], m_color._v[3]); > } > > } > else > { > curGeom->setColorArray(m_colorArrays.get()); > curGeom->setColorBinding(osg::Geometry::BIND_OVERALL); > } > } > } > }; > > void ColorVisitor::setColor(const float r, const float g, const float b, > const float a) > { > // --- > // > // Set the color to change apply to the nodes geometry > // > // --- > osg::Vec4 *c = &m_colorArrays->operator [](0); > m_color.set(r, g, b, a); > *c = m_color; > }; > > void ColorVisitor::setColor(const osg::Vec4 &color) { > // --- > // > // Set the color to change apply to the nodes geometry > // > // --- > osg::Vec4 *c = &m_colorArrays->operator [](0); > m_color = color; > *c = m_color; > }; > > > > > > Cheers, > > ---
Re: [osg-users] Update node color on demand
Hello Trajce, The visitor class implementation is on my previous post on this thread. I took that code from Gordon Tomlison's OSG Samples, and it works when is used previous to the rendering as you can see on my initial post (other thread: http://forum.openscenegraph.org/viewtopic.php?p=75209#75209). As I said everything gets called when it should, but on runtime, the lines wont change color. I you look at the code snippet of my main: Code: _lines = osgDB::readNodeFile("lines.dxf"); _topo->setDataVariance(osg::Object::DYNAMIC); osg::Geode* geode = new osg::Geode; _mViewer->addEventHandler(new ColorHandler); ColorVisitor newColor; newColor.setColor( 1.0f, 0.0f, 0.0f ); _lines->accept(newColor); geode->addChild(_lines); _mViewer->realize(); The color of the lines turns red on start. But then, when I try to change it to another color on runetime, nothing happens. Anyway, here is the visitor implementation (.cpp): Code: ColorVisitor::ColorVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { m_color.set(1.0, 1.0, 1.0, 1.0); m_colorArrays = new osg::Vec4Array; m_colorArrays->push_back(m_color); }; ColorVisitor::ColorVisitor(const osg::Vec4 &color): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { m_color = color; m_colorArrays = new osg::Vec4Array; m_colorArrays->push_back(m_color); }; ColorVisitor::~ColorVisitor() { }; void ColorVisitor::apply(osg::Node &node) { // // // Handle traversal of osg::Node node types // // traverse(node); }; void ColorVisitor::apply(osg::Geode &geode) { // // // Handle traversal of osg::Geode node types // // osg::StateSet *state = NULL; unsigned intvertNum = 0; // // We need to iterate through all the drawables check if // the contain any geometry that we will need to process // unsigned int numGeoms = geode.getNumDrawables(); for (unsigned int geodeIdx = 0; geodeIdx < numGeoms; geodeIdx++) { // // Use 'asGeometry' as its supposed to be faster than a dynamic_cast // every little saving counts // osg::Geometry *curGeom = geode.getDrawable(geodeIdx)->asGeometry(); // // Only process if the drawable is geometry // if (curGeom) { osg::Vec4Array *colorArrays = dynamic_cast(curGeom->getColorArray()); if (colorArrays) { for (unsigned int i = 0; i < colorArrays->size(); i++) { osg::Vec4 *color = &colorArrays->operator [](i); // // could also use *color = m_color // color->set(m_color._v[0], m_color._v[1], m_color._v[2], m_color._v[3]); } } else { curGeom->setColorArray(m_colorArrays.get()); curGeom->setColorBinding(osg::Geometry::BIND_OVERALL); } } } }; void ColorVisitor::setColor(const float r, const float g, const float b, const float a) { // --- // // Set the color to change apply to the nodes geometry // // --- osg::Vec4 *c = &m_colorArrays->operator [](0); m_color.set(r, g, b, a); *c = m_color; }; void ColorVisitor::setColor(const osg::Vec4 &color) { // --- // // Set the color to change apply to the nodes geometry // // --- osg::Vec4 *c = &m_colorArrays->operator [](0); m_color = color; *c = m_color; }; Cheers, -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=75248#75248 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Update node color on demand
Hi Diego, can you post your Visitor code? It can be something like missing calling ->dirty() on the color array or such On Mon, Nov 26, 2018 at 8:30 PM Diego Mancilla wrote: > Hello, > > I have tried Eran's suggestion with no success. I have successfully > created the handler, and it gets called but no color change... > > My current code: > > On main: > > Code: > _lines = osgDB::readNodeFile("lines.dxf"); > _topo->setDataVariance(osg::Object::DYNAMIC); > osg::Geode* geode = new osg::Geode; > > _mViewer->addEventHandler(new ColorHandler); > > ColorVisitor newColor; > newColor.setColor( 1.0f, 0.0f, 0.0f ); > _lines->accept(newColor); > geode->addChild(_lines); > _mViewer->realize(); > > > > > The handler: > > > Code: > bool ColorHandler::handle(const osgGA::GUIEventAdapter& ea, > osgGA::GUIActionAdapter& aa) > { > if (ea.getEventType() == ea.USER) > { > auto changeColorEvent = dynamic_cast ChangeColorEvent*>(ea.getUserData()); > if (changeColorEvent != nullptr) > { > std::cout << "Hola Handler!!!" << std::endl; > std::cout << "new color: " << > changeColorEvent->r<<" "<< changeColorEvent->g<< " "<< > changeColorEvent->b< ColorVisitor newColor; > newColor.setColor(changeColorEvent->r, > changeColorEvent->g, changeColorEvent->b); > changeColorEvent->node->accept(newColor); > return true; > } > } > return false; > > > > Thank you! > > Cheers, > Diego > > -- > Read this topic online here: > http://forum.openscenegraph.org/viewtopic.php?p=75245#75245 > > > > > > ___ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > -- trajce nikolov nick ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Update node color on demand
Hello, I have tried Eran's suggestion with no success. I have successfully created the handler, and it gets called but no color change... My current code: On main: Code: _lines = osgDB::readNodeFile("lines.dxf"); _topo->setDataVariance(osg::Object::DYNAMIC); osg::Geode* geode = new osg::Geode; _mViewer->addEventHandler(new ColorHandler); ColorVisitor newColor; newColor.setColor( 1.0f, 0.0f, 0.0f ); _lines->accept(newColor); geode->addChild(_lines); _mViewer->realize(); The handler: Code: bool ColorHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { if (ea.getEventType() == ea.USER) { auto changeColorEvent = dynamic_cast(ea.getUserData()); if (changeColorEvent != nullptr) { std::cout << "Hola Handler!!!" << std::endl; std::cout << "new color: " << changeColorEvent->r<<" "<< changeColorEvent->g<< " "<< changeColorEvent->bg, changeColorEvent->b); changeColorEvent->node->accept(newColor); return true; } } return false; Thank you! Cheers, Diego -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=75245#75245 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Update node color on demand
Hello Eran, Thank you again. I will try what you suggest. Cheers, -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=75244#75244 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Update node color on demand
Hi Diego, You can pass user events to the viewer (and thus to its Event Handlers): Code: // This struct will be passed to the event handler with the relevant parameters (for example, the node you want to affect and the color to change it to) struct ChangeColorEvent : public osg::Referenced { ChangeColorEvent(float r, float g, float b, osg::Node* node) { this->r = r; this->g = g; this->b = b; this->node = node; } float r; float g; float b; osg::Node* node; } // When you want to call the event (on a button click in QT for example) viewer->getEventQueue()->userEvent(new ChangeColorEvent{ 1.0, 0.3, 0.4, node }, 0); To handle said event in your EventHandler: Code: class ColorHandler : public osgGA::GUIEventHandler { virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override { if (ea.getEventType() == ea.USER) { auto changeColorEvent = dynamic_cast(ea.getUserData()); if (changeColorEvent != nullptr) { // do whatever you want here, for example run the visitor on the node return true; } } return false; } }; Cheers, Eran -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=75241#75241 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Update node color on demand
Hello Eran, Thank you very much for your answer. I should have been more explicit, due to the fact than I'm a newbie on OSG (and 3D development). I have an OSG viewer embedded on a Qt5 application. So the idea is that the user can change the color of one node (some dxf lines) on demand though the GUI (some dialog, pushing buttons, etc). So, bottom line... at some point at runtime I have a fresh new color (rgb, for instance) and I need to pass it to the viewer towards the "_lines" node. As I previuosly stated I'm new to OSG and I'm just digesting the scene graph scheme. So, how can I pass this information from the Qt5 environment, to the to the node using your suggestions? Thank you in advance! Cheers, -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=75240#75240 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Update node color on demand
Hi, To respond to user events you can either inherit from osg::Callback and install it on your node as an EventCallback: Code: class ColorCallback : public osg::Callback { public: virtual bool run(osg::Object* object, osg::Object* data) override { auto nv = dynamic_cast(data); if (nv != nullptr && nv->getVisitorType() == nv->EVENT_VISITOR) { auto events = nv->asEventVisitor()->getEvents(); for (auto event : events) { // handle events } } return traverse(object, data); } }; _lines->addEventCallback(new ColorCallback); or use a global EventHandler and install it on your Viewer: Code: class ColorHandler : public osgGA::GUIEventHandler { virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override { if (ea.getEventType() == ea.KEYDOWN) { // handle event } } }; viewer->addEventHandler(new ColorHandler); Cheers, Eran -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=75239#75239 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
[osg-users] Update node color on demand
Hello, I'm trying to change a node color on demand from my application. The idea is that the user, once the initial rendering took place can change the color of a node by pressing a key (or something similar). I know already hoy to change the color using a NodeVisitor (previous to the rendering). Code: ColorVisitor newColor; newColor.setColor(r, g, b); _lines->accept(newColor); Where _lines is a Node reference pointer and ColorVisitor is a subclass of NodeVisitor (http://forum.openscenegraph.org/viewtopic.php?p=75209#75209). I tried to create a callback and attach it to the node but the callback get called every time and I cant pass to it the selected color on runtime. Can anyone give some pointer about this issue? Thank you! Cheers, [/url] -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=75238#75238 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org