SoGLHighlightRenderAction.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package MemoryX::gui-plugins::SceneEditor
19  * @date 2015
20  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21  * GNU General Public License
22  */
23 
24 /*
25  * SoGLHighlightRenderAction.cpp
26  *
27  * Created on: Jan 13, 2015
28  * Author: philipp
29  */
30 
32 
34  const SbViewportRegion& viewportregion,
35  Scene* scene) :
36  SoGLRenderAction(viewportregion),
37  scene(scene),
38  selectedcolor_storage(sizeof(void*), alloc_colorpacker, free_colorpacker)
39 {
40 
41  this->isVisible = true;
42  this->selectedColor = SbColor(1.0f, 0.8f, 0.4f);
43  this->activeColor = SbColor(1.0f, 0.4f, 0.2f);
44  this->linepattern = 0xffff;
45  this->linewidth = 5;
46 
47  // SoBase-derived objects should be dynamically allocated.
48  this->postprocpath = new SoTempPath(32);
49  this->postprocpath->ref();
50 }
51 
53 {
54  postprocpath->unref();
55 }
56 
57 void
59 {
60  std::unique_lock lock(scene->execute_mutex);
61 
62  //Render complete scene with standard action
63  SoGLRenderAction::apply(node);
64 
65  if (this->isVisible)
66  {
67  SoSearchAction* searchAction = new SoSearchAction;
68  searchAction->setType(SoSelection::getClassTypeId());
69  searchAction->setInterest(SoSearchAction::ALL);
70  searchAction->apply(node);
71 
72  const SoPathList& pathlist = searchAction->getPaths();
73 
74  if (pathlist.getLength() > 0)
75  {
76  for (int i = 0; i < pathlist.getLength(); i++)
77  {
78  SoPath* path = pathlist[i];
79  SoSelection* selection = (SoSelection*)path->getTail();
80 
81  if (selection->getNumSelected() > 0)
82  //Add highlight border around selected objects
83  {
84  this->drawHighlight(path, selection->getList());
85  }
86  }
87  }
88  }
89 }
90 
91 void
92 scene3D::SoGLHighlightRenderAction::drawHighlight(SoPath* pathtothis, const SoPathList* pathlist)
93 {
94  // Copied from Coin implementation, no idea what it does
95  int oldnumpasses = this->getNumPasses();
96  this->setNumPasses(1);
97 
98  //Insert path to SoSelection node in our postprocesspath
99  int thispos = ((SoFullPath*)pathtothis)->getLength() - 1;
100  this->postprocpath->truncate(0);
101 
102  for (int i = 0; i < thispos; i++)
103  {
104  this->postprocpath->append(pathtothis->getNode(i));
105  }
106 
107  //For 0 to n - 1 selected object of selection list render colored wireframe
108  for (int i = 0; i < pathlist->getLength(); i++)
109  {
110  //Retrieve full path
111  SoFullPath* path = (SoFullPath*)(*pathlist)[i];
112 
113  //Append to postprocesspath
114  for (int j = 0; j < path->getLength(); j++)
115  {
116  this->postprocpath->append(path->getNode(j));
117  }
118 
119  /*
120  We use a little algorithm mostly explained here:
121  http://www.flipcode.com/archives/Object_Outlining.shtml
122  and here:
123  http://www.informit.com/articles/article.aspx?p=328646&seqNum=10
124 
125  We basically fill the opengl stencil buffer with the value 1,
126  tell opengl to never touch the color buffer but modify the stencil buffer only.
127  (Actually writing zero into it at the respective pixel positions).
128  In the next step we render the object again, this time drawing
129  the wireframe version of the object with the selection color
130  and only drawing where we still have the value 1 in stencil buffer.
131  Because line width is 5, we actually get some sort of 'edge glow'
132  effect out of this. :)
133  */
134 
135  // Use 1 for clearing stencil buffer, clear buffer and enable stencil test
136  glEnable(GL_STENCIL_TEST);
137  glClearStencil(1.0f);
138  glClear(GL_STENCIL_BUFFER_BIT);
139 
140  // All drawing commands fail the stencil test and are not
141  // drawn, but set the value in the stencil buffer to zero.
142  glStencilFunc(GL_NEVER, 0x0, 0x0);
143  glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
144  SoGLRenderAction::apply(this->postprocpath);
145 
146  //Render only where stencil is not set to 0, to achieve sort of 'edge glow' effect
147  glStencilFunc(GL_NOTEQUAL, 0, 1);
148  //Do not modify stencil buffer in any way (just to keep it clean, doesn't really matter)
149  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
150 
151  //Draw wireframe in selection color, masked by stencil
152  drawWireframe(this->postprocpath, i == pathlist->getLength() - 1);
153 
154  //Reset postprocesspath to SoSelection node
155  this->postprocpath->truncate(thispos);
156 
157  glDisable(GL_STENCIL_TEST);
158  }
159 
160  //Restore this mysterious numpass thing
161  this->setNumPasses(oldnumpasses);
162 }
163 
164 void
165 scene3D::SoGLHighlightRenderAction::drawWireframe(SoPath* pathtothis, bool active)
166 {
167  //Save current openGL state
168  SoState* state = this->getState();
169  state->push();
170 
171  //Cause Coin sucks we have to use OpenGL calls directly here
172  //because calling SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR)
173  //ends in SEGFAULT for some selected objects
174  glDisable(GL_LIGHTING);
175 
176  //Do some pretty complex and fun OpenGL adaptions
177  SoColorPacker** selected_cptr = (SoColorPacker**)this->selectedcolor_storage.get();
178 
179  if (!active)
180  {
181  SoGLLazyElement::setDiffuse(
182  state, pathtothis->getHead(), 1, &this->selectedColor, *selected_cptr);
183  }
184  else
185  {
186  //Set new color for last object
187  SoGLLazyElement::setDiffuse(
188  state, pathtothis->getTail(), 1, &this->activeColor, *selected_cptr);
189  }
190 
191  SoLineWidthElement::set(state, this->linewidth);
192  SoLinePatternElement::set(state, this->linepattern);
193  SoTextureQualityElement::set(state, 0.0f);
194  SoDrawStyleElement::set(state, SoDrawStyleElement::LINES);
195  SoPolygonOffsetElement::set(state, NULL, -1.0f, 1.0f, SoPolygonOffsetElement::LINES, TRUE);
196  SoMaterialBindingElement::set(state, NULL, SoMaterialBindingElement::OVERALL);
197  SoNormalElement::set(state, NULL, 0, NULL, FALSE);
198  SoOverrideElement::setNormalVectorOverride(state, NULL, TRUE);
199  SoOverrideElement::setMaterialBindingOverride(state, NULL, TRUE);
200  SoOverrideElement::setLightModelOverride(state, NULL, TRUE);
201  SoOverrideElement::setDiffuseColorOverride(state, NULL, TRUE);
202  SoOverrideElement::setLineWidthOverride(state, NULL, TRUE);
203  SoOverrideElement::setLinePatternOverride(state, NULL, TRUE);
204  SoOverrideElement::setDrawStyleOverride(state, NULL, TRUE);
205  SoOverrideElement::setPolygonOffsetOverride(state, NULL, TRUE);
206  SoTextureOverrideElement::setQualityOverride(state, TRUE);
207 
208  //Render with new OpenGL context
209  SoGLRenderAction::apply(this->postprocpath);
210 
211  //Cause switching light on again might be a good idea
212  glEnable(GL_LIGHTING);
213 
214  //Restore OpenGL context
215  state->pop();
216 }
scene3D::Scene
Definition: Scene.h:60
scene3D::SoGLHighlightRenderAction::~SoGLHighlightRenderAction
~SoGLHighlightRenderAction() override
Destructor.
Definition: SoGLHighlightRenderAction.cpp:52
scene3D::SoGLHighlightRenderAction::apply
void apply(SoNode *node) override
Applies the Highlighting to a given node.
Definition: SoGLHighlightRenderAction.cpp:58
scene3D::SoGLHighlightRenderAction::SoGLHighlightRenderAction
SoGLHighlightRenderAction(const SbViewportRegion &viewportregion, Scene *scene)
Constructor Creates an Instance of the Class.
Definition: SoGLHighlightRenderAction.cpp:33
SoGLHighlightRenderAction.h
scene3D::ALL
@ ALL
Definition: ManipulatorMode.h:35
set
set(LIBS ArmarXCoreInterfaces ${CMAKE_THREAD_LIBS_INIT} ${dl_LIBRARIES} ${rt_LIBRARIES} ${QT_LIBRARIES} ${Boost_LIBRARIES} BoostAssertionHandler ArmarXCPPUtility SimoxUtility) set(LIB_FILES ArmarXManager.cpp ArmarXMultipleObjectsScheduler.cpp ArmarXObjectScheduler.cpp ManagedIceObject.cpp ManagedIceObjectPlugin.cpp Component.cpp ComponentPlugin.cpp IceGridAdmin.cpp ArmarXObjectObserver.cpp IceManager.cpp PackagePath.cpp RemoteReferenceCount.cpp logging/LoggingUtil.cpp logging/Logging.cpp logging/LogSender.cpp logging/ArmarXLogBuf.cpp system/ArmarXDataPath.cpp system/DynamicLibrary.cpp system/ProcessWatcher.cpp system/FactoryCollectionBase.cpp system/cmake/CMakePackageFinder.cpp system/cmake/CMakePackageFinderCache.cpp system/cmake/ArmarXPackageToolInterface.cpp system/RemoteObjectNode.cpp services/sharedmemory/HardwareId.cpp services/tasks/RunningTask.cpp services/tasks/ThreadList.cpp services/tasks/ThreadPool.cpp services/profiler/Profiler.cpp services/profiler/FileLoggingStrategy.cpp services/profiler/IceLoggingStrategy.cpp application/Application.cpp application/ApplicationOptions.cpp application/ApplicationProcessFacet.cpp application/ApplicationNetworkStats.cpp application/properties/PropertyUser.cpp application/properties/Property.cpp application/properties/PropertyDefinition.cpp application/properties/PropertyDefinitionContainer.cpp application/properties/PropertyDefinitionHelpFormatter.cpp application/properties/PropertyDefinitionConfigFormatter.cpp application/properties/PropertyDefinitionBriefHelpFormatter.cpp application/properties/PropertyDefinitionXmlFormatter.cpp application/properties/PropertyDefinitionDoxygenFormatter.cpp application/properties/PropertyDefinitionDoxygenComponentPagesFormatter.cpp application/properties/PropertyDefinitionContainerBriefHelpFormatter.cpp application/properties/IceProperties.cpp exceptions/Exception.cpp exceptions/local/UnexpectedEnumValueException.cpp util/FileSystemPathBuilder.cpp util/StringHelpers.cpp util/IceReportSkipper.cpp util/Throttler.cpp util/distributed/AMDCallbackCollection.cpp util/distributed/RemoteHandle/ClientSideRemoteHandleControlBlock.cpp util/distributed/RemoteHandle/RemoteHandle.cpp util/distributed/RemoteHandle/RemoteHandleControlBlock.cpp time/ice_conversions.cpp time/json_conversions.cpp time/CallbackWaitLock.cpp time/Clock.cpp time/ClockType.cpp time/ClockTypeNames.cpp time/CycleUtil.cpp time/DateTime.cpp time/Duration.cpp time/Frequency.cpp time/LocalTimeServer.cpp time/Metronome.cpp time/ScopedStopWatch.cpp time/StopWatch.cpp time/Timer.cpp time/TimeKeeper.cpp time/TimeUtil.cpp csv/CsvWriter.cpp csv/CsvReader.cpp eigen/conversions.cpp eigen/ice_conversions.cpp) set(LIB_HEADERS ArmarXManager.h ArmarXDummyManager.h ArmarXMultipleObjectsScheduler.h ArmarXObjectObserver.h ArmarXObjectScheduler.h ArmarXFwd.h Component.h ComponentPlugin.h ComponentFactories.h CoreObjectFactories.h IceGridAdmin.h IceManager.h IceManagerImpl.h json_conversions.h ManagedIceObject.h ManagedIceObjectPlugin.h ManagedIceObjectImpl.h ManagedIceObjectDependency.h ManagedIceObjectRegistryInterface.h PackagePath.h RemoteReferenceCount.h system/ImportExport.h system/ImportExportComponent.h system/AbstractFactoryMethod.h system/FactoryCollectionBase.h system/Synchronization.h system/ArmarXDataPath.h system/DynamicLibrary.h system/ProcessWatcher.h system/ConditionSynchronization.h system/cmake/CMakePackageFinder.h system/cmake/CMakePackageFinderCache.h system/cmake/FindPackageX.cmake system/cmake/ArmarXPackageToolInterface.h system/RemoteObjectNode.h logging/LoggingUtil.h logging/LogSender.h logging/Logging.h logging/ArmarXLogBuf.h logging/SpamFilterData.h services/tasks/RunningTask.h services/tasks/PeriodicTask.h services/tasks/ThreadList.h services/tasks/TaskUtil.h services/tasks/ThreadPool.h services/sharedmemory/SharedMemoryProvider.h services/sharedmemory/SharedMemoryConsumer.h services/sharedmemory/IceSharedMemoryProvider.h services/sharedmemory/IceSharedMemoryConsumer.h services/sharedmemory/HardwareIdentifierProvider.h services/sharedmemory/HardwareId.h services/sharedmemory/exceptions/SharedMemoryExceptions.h services/profiler/Profiler.h services/profiler/LoggingStrategy.h services/profiler/FileLoggingStrategy.h services/profiler/IceLoggingStrategy.h application/Application.h application/ApplicationOptions.h application/ApplicationProcessFacet.h application/ApplicationNetworkStats.h application/properties/forward_declarations.h application/properties/Properties.h application/properties/Property.h application/properties/PluginEigen.h application/properties/PluginEnumNames.h application/properties/PluginCfgStruct.h application/properties/PluginAll.h application/properties/PropertyUser.h application/properties/PropertyDefinition.h application/properties/PropertyDefinition.hpp application/properties/PropertyDefinitionInterface.h application/properties/PropertyDefinitionContainer.h application/properties/PropertyDefinitionFormatter.h application/properties/PropertyDefinitionContainerFormatter.h application/properties/PropertyDefinitionConfigFormatter.h application/properties/PropertyDefinitionHelpFormatter.h application/properties/PropertyDefinitionBriefHelpFormatter.h application/properties/PropertyDefinitionXmlFormatter.h application/properties/PropertyDefinitionDoxygenFormatter.h application/properties/PropertyDefinitionDoxygenComponentPagesFormatter.h application/properties/PropertyDefinitionContainerBriefHelpFormatter.h application/properties/ProxyPropertyDefinition.h application/properties/IceProperties.h exceptions/Exception.h exceptions/LocalException.h exceptions/local/DynamicLibraryException.h exceptions/local/ExpressionException.h exceptions/local/FileIOException.h exceptions/local/InvalidPropertyValueException.h exceptions/local/MissingRequiredPropertyException.h exceptions/local/PropertyInheritanceCycleException.h exceptions/local/ProxyNotInitializedException.h exceptions/local/UnexpectedEnumValueException.h exceptions/local/UnmappedValueException.h exceptions/local/ValueRangeExceededException.h exceptions/user/NotImplementedYetException.h rapidxml/rapidxml.hpp rapidxml/rapidxml_print.hpp rapidxml/rapidxml_iterators.hpp rapidxml/rapidxml_utils.hpp rapidxml/wrapper/RapidXmlReader.h rapidxml/wrapper/RapidXmlWriter.h rapidxml/wrapper/DefaultRapidXmlReader.h rapidxml/wrapper/MultiNodeRapidXMLReader.h util/IceBlobToObject.h util/ObjectToIceBlob.h util/FileSystemPathBuilder.h util/FiniteStateMachine.h util/StringHelpers.h util/StringHelperTemplates.h util/algorithm.h util/OnScopeExit.h util/Predicates.h util/Preprocessor.h util/PropagateConst.h util/Registrar.h util/TemplateMetaProgramming.h util/TripleBuffer.h util/IceReportSkipper.h util/Throttler.h util/distributed/AMDCallbackCollection.h util/distributed/RemoteHandle/ClientSideRemoteHandleControlBlock.h util/distributed/RemoteHandle/RemoteHandle.h util/distributed/RemoteHandle/RemoteHandleControlBlock.h util/SimpleStatemachine.h time.h time_minimal.h time/forward_declarations.h time/ice_conversions.h time/json_conversions.h time/CallbackWaitLock.h time/Clock.h time/ClockType.h time/ClockTypeNames.h time/CycleUtil.h time/DateTime.h time/Duration.h time/Frequency.h time/LocalTimeServer.h time/Metronome.h time/ScopedStopWatch.h time/StopWatch.h time/Timer.h time/TimeUtil.h time/TimeKeeper.h csv/CsvWriter.h csv/CsvReader.h eigen/conversions.h eigen/ice_conversions.h ice_conversions.h ice_conversions/ice_conversions_boost_templates.h ice_conversions/ice_conversions_templates.h ice_conversions/ice_conversions_templates.tpp $
Definition: CMakeLists.txt:12