Hi Nick,
the triangle shown in white has just being added to highlight the selection. We
can discard it for a while. For that reason I completly removed the selection
highlight in my example. Please see attached code.
If you run the example and select a triangle pushing CTRL+LEFTMOUSE you will
see a couple of messages on the console, something like:
"moving from primitive 1 to 0
... BUT why triangle does not change color?"
That's the point!
In my example I have 4 primitive sets:
index 0 = red
index 1 = green
index 2 = blue
index 3 = pink
Picking a green triangle it is moved from the original primitive set (1 i.e.
green) to the primitive set with index = 0 (i.e. red). But why the triangle
moved from green to red is still green? I would expect it to be red.
Regards,
Gianni
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=68692#68692
#include "stdafx.h"
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/MatrixTransform>
#include <osg/PolygonOffset>
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgDB/ReadFile>
#include <osgQt/GraphicsWindowQt>
#include <iostream>
const osg::Vec4 selectedColor(1.0f, 1.0f, 1.0f, 0.5f);
const osg::Vec4 color1(1.0f, 0.0f, 0.0f, 1.0f);
const osg::Vec4 color2(0.0f, 1.0f, 0.0f, 1.0f);
const osg::Vec4 color3(0.0f, 0.0f, 1.0f, 1.0f);
const osg::Vec4 color4(1.0f, 0.0f, 1.0f, 1.0f);
class SelectModelHandler : public osgGA::GUIEventHandler
{
public:
SelectModelHandler() : _selector(0), currentPrimitiveSetIndex(0) {}
virtual bool handle( const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa )
{
if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE &&
ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
{
_selector->setVertexArray( new osg::Vec3Array(3) );
}
if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE &&
ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON &&
ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL)
{
osgViewer::View* viewer = dynamic_cast<osgViewer::View*>(&aa);
if ( viewer )
{
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new
osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, ea.getX(),
ea.getY());
osgUtil::IntersectionVisitor iv(intersector.get());
osg::Camera* camera = viewer->getCamera();
camera->accept( iv );
if ( intersector->containsIntersections() )
{
osgUtil::LineSegmentIntersector::Intersection result =
*(intersector->getIntersections().begin());
doUserOperations( result );
}
}
}
if (ea.getKey() == osgGA::GUIEventAdapter::KEY_1) {
currentPrimitiveSetIndex = 0;
}
if (ea.getKey() == osgGA::GUIEventAdapter::KEY_2) {
currentPrimitiveSetIndex = 1;
}
if (ea.getKey() == osgGA::GUIEventAdapter::KEY_3) {
currentPrimitiveSetIndex = 2;
}
if (ea.getKey() == osgGA::GUIEventAdapter::KEY_4) {
currentPrimitiveSetIndex = 3;
}
return false;
}
virtual void doUserOperations(
osgUtil::LineSegmentIntersector::Intersection& result )
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(
result.drawable.get() );
//if ( !geom || !_selector || geom==_selector ) return;
osg::Geode* geode =
dynamic_cast<osg::Geode*>(result.nodePath[result.nodePath.size()-1]);
unsigned int primitiveIndex =
getPrimitiveIndex(dynamic_cast<osg::Geometry*>(geode->getDrawable(0)),
result.primitiveIndex);
unsigned int indexInsidePrimitive =
getIndexInsidePrimitive(dynamic_cast<osg::Geometry*>(geode->getDrawable(0)),
result.primitiveIndex);
if (primitiveIndex != currentPrimitiveSetIndex) {
std::cout << "moving from primitive " << primitiveIndex << " to " <<
currentPrimitiveSetIndex << std::endl;
move(dynamic_cast<osg::Geometry*>(geode->getDrawable(0)),
primitiveIndex, indexInsidePrimitive, currentPrimitiveSetIndex);
std::cout << "... BUT why triangle does not change color?" <<
std::endl;
} else {
std::cout << "nothing to move" << std::endl;
}
}
unsigned int getPrimitiveIndex(osg::Geometry* geometry, unsigned int
globalIndex)
{
unsigned int numPrimitives = geometry->getNumPrimitiveSets();
unsigned int currentPrimitive = numPrimitives;
unsigned int globalCount = 0;
for (int i=0; i<numPrimitives; ++i) {
osg::PrimitiveSet* primitiveSet = geometry->getPrimitiveSet(i);
unsigned int count = primitiveSet->getNumPrimitives();
if (globalCount <= globalIndex && globalIndex < globalCount+count) {
currentPrimitive = i;
break;
} else {
globalCount += count;
}
}
return currentPrimitive;
}
unsigned int getIndexInsidePrimitive(osg::Geometry* geometry, unsigned int
globalIndex)
{
unsigned int numPrimitives = geometry->getNumPrimitiveSets();
unsigned int index = 0;
unsigned int globalCount = 0;
for (int i=0; i<numPrimitives; ++i) {
osg::PrimitiveSet* primitiveSet = geometry->getPrimitiveSet(i);
unsigned int count = primitiveSet->getNumPrimitives();
if (globalCount <= globalIndex && globalIndex < globalCount+count) {
index = globalIndex - globalCount;
break;
} else {
globalCount += count;
}
}
return index;
}
void move(osg::Geometry* geometry, unsigned int sourcePrimitiveSetIndex,
unsigned int elementIndex, unsigned int destinationPrimitiveSetIndex)
{
osg::DrawElementsUInt* sourcePrimitiveSet =
dynamic_cast<osg::DrawElementsUInt*>(geometry->getPrimitiveSet(sourcePrimitiveSetIndex));
osg::DrawElementsUInt* destinationPrimitiveSet =
dynamic_cast<osg::DrawElementsUInt*>(geometry->getPrimitiveSet(destinationPrimitiveSetIndex));
destinationPrimitiveSet->push_back(sourcePrimitiveSet->at(elementIndex*3));
destinationPrimitiveSet->push_back(sourcePrimitiveSet->at(elementIndex*3+1));
destinationPrimitiveSet->push_back(sourcePrimitiveSet->at(elementIndex*3+2));
sourcePrimitiveSet->erase(sourcePrimitiveSet->begin()+elementIndex*3);
sourcePrimitiveSet->erase(sourcePrimitiveSet->begin()+elementIndex*3);
sourcePrimitiveSet->erase(sourcePrimitiveSet->begin()+elementIndex*3);
sourcePrimitiveSet->dirty();
destinationPrimitiveSet->dirty();
geometry->dirtyBound();
}
protected:
osg::ref_ptr<osg::Geometry> _selector;
unsigned int currentPrimitiveSetIndex;
};
osg::Vec3Array* buildVertices() {
osg::Vec3Array* vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(0,0,0));
vertices->push_back(osg::Vec3(10,0,0));
vertices->push_back(osg::Vec3(10,10,0));
vertices->push_back(osg::Vec3(0,10,0));
vertices->push_back(osg::Vec3(20,0,0));
vertices->push_back(osg::Vec3(20,10,0));
vertices->push_back(osg::Vec3(20,20,0));
vertices->push_back(osg::Vec3(10,20,0));
vertices->push_back(osg::Vec3(0,20,0));
return vertices;
}
osg::DrawElementsUInt* buildElement1() {
osg::DrawElementsUInt* element = new
osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
element->push_back(0);
element->push_back(1);
element->push_back(2);
element->push_back(0);
element->push_back(2);
element->push_back(3);
return element;
}
osg::DrawElementsUInt* buildElement2() {
osg::DrawElementsUInt* element = new
osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
element->push_back(1);
element->push_back(4);
element->push_back(5);
element->push_back(1);
element->push_back(5);
element->push_back(2);
return element;
}
osg::DrawElementsUInt* buildElement3() {
osg::DrawElementsUInt* element = new
osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
element->push_back(2);
element->push_back(5);
element->push_back(6);
element->push_back(2);
element->push_back(6);
element->push_back(7);
return element;
}
osg::DrawElementsUInt* buildElement4() {
osg::DrawElementsUInt* element = new
osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
element->push_back(3);
element->push_back(2);
element->push_back(7);
element->push_back(3);
element->push_back(7);
element->push_back(8);
return element;
}
osg::Vec4Array* buildColors() {
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
colors->push_back(osg::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
return colors;
}
osg::Geometry* buildGeometry() {
osg::Geometry* geometry = new osg::Geometry;
geometry->setDataVariance(osg::Object::DYNAMIC);
geometry->setVertexArray(buildVertices());
geometry->setColorArray(buildColors(), osg::Array::BIND_PER_PRIMITIVE_SET);
geometry->addPrimitiveSet(buildElement1());
geometry->addPrimitiveSet(buildElement2());
geometry->addPrimitiveSet(buildElement3());
geometry->addPrimitiveSet(buildElement4());
return geometry;
}
osg::Node* createScene() {
osg::Geode* geode = new osg::Geode;
geode->addDrawable(buildGeometry());
return geode;
}
int main( int argc, char** argv )
{
osg::ArgumentParser arguments(&argc, argv);
osgViewer::Viewer viewer(arguments);
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(createScene());
osg::ref_ptr<SelectModelHandler> selector = new SelectModelHandler;
viewer.setSceneData(root);
viewer.addEventHandler(selector.get());
viewer.setCameraManipulator( new osgGA::TrackballManipulator );
// add the window size toggle handler
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
viewer.run();
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org