/*========================================================================= Program: Visualization Toolkit Module: vtkCompositePainter.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkCompositePainter.h" #include "vtkColor.h" #include "vtkCompositeDataDisplayAttributesLegacy.h" #include "vtkCompositeDataIterator.h" #include "vtkCompositeDataSet.h" #include "vtkGarbageCollector.h" #include "vtkHardwareSelector.h" #include "vtkInformation.h" #include "vtkInformationObjectBaseKey.h" #include "vtkMultiBlockDataSet.h" #include "vtkMultiPieceDataSet.h" #include "vtkObjectFactory.h" #include "vtkPolyData.h" #include "vtkProperty.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include // Return NULL if no override is supplied. vtkAbstractObjectFactoryNewMacro(vtkCompositePainter) vtkInformationKeyMacro(vtkCompositePainter, DISPLAY_ATTRIBUTES, ObjectBase); vtkCxxSetObjectMacro(vtkCompositePainter, CompositeDataDisplayAttributes, vtkCompositeDataDisplayAttributesLegacy); //---------------------------------------------------------------------------- vtkCompositePainter::vtkCompositePainter() { this->OutputData = 0; this->CompositeDataDisplayAttributes = 0; } //---------------------------------------------------------------------------- vtkCompositePainter::~vtkCompositePainter() { this->SetCompositeDataDisplayAttributes(0); } //---------------------------------------------------------------------------- vtkDataObject* vtkCompositePainter::GetOutput() { return this->OutputData? this->OutputData : this->GetInput(); } //---------------------------------------------------------------------------- void vtkCompositePainter::RenderInternal(vtkRenderer* renderer, vtkActor* actor, unsigned long typeflags, bool forceCompileOnly) { vtkCompositeDataSet* input = vtkCompositeDataSet::SafeDownCast(this->GetInput()); if (!input || !this->DelegatePainter) { this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly); return; } vtkHardwareSelector* selector = renderer->GetSelector(); if (this->CompositeDataDisplayAttributes && (this->CompositeDataDisplayAttributes->HasBlockOpacities() || this->CompositeDataDisplayAttributes->HasBlockVisibilities() || this->CompositeDataDisplayAttributes->HasBlockColors())) { vtkProperty* prop = actor->GetProperty(); RenderBlockState state; // Push base-values on the state stack. state.Visibility.push(true); state.Opacity.push(prop->GetOpacity()); state.AmbientColor.push(vtkColor3d(prop->GetAmbientColor())); state.DiffuseColor.push(vtkColor3d(prop->GetDiffuseColor())); state.SpecularColor.push(vtkColor3d(prop->GetSpecularColor())); // OpenGL currently knows how to render *this* state. state.RenderedOpacity = state.Opacity.top(); state.RenderedAmbientColor = state.AmbientColor.top(); state.RenderedDiffuseColor = state.DiffuseColor.top(); state.RenderedSpecularColor = state.SpecularColor.top(); // render using the composite data attributes unsigned int flat_index = 0; this->RenderBlock(renderer, actor, typeflags, forceCompileOnly, input, flat_index, state); // restore OpenGL state, if it was changed. this->UpdateRenderingState(renderer->GetRenderWindow(), actor->GetProperty(), state); } else { // render using the multi-block structure itself vtkCompositeDataIterator* iter = input->NewIterator(); for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem()) { vtkDataObject* dobj = iter->GetCurrentDataObject(); if (dobj) { if (selector) { selector->BeginRenderProp(); // If hardware selection is in progress, we need to pass the composite // index to the selection framework, selector->RenderCompositeIndex(iter->GetCurrentFlatIndex()); } this->DelegatePainter->SetInput(dobj); this->OutputData = dobj; this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly); this->OutputData = 0; if (selector) { selector->EndRenderProp(); } } } iter->Delete(); } } //----------------------------------------------------------------------------- void vtkCompositePainter::RenderBlock(vtkRenderer *renderer, vtkActor *actor, unsigned long typeflags, bool forceCompileOnly, vtkDataObject *dobj, unsigned int &flat_index, vtkCompositePainter::RenderBlockState &state) { assert("Sanity Check" && (state.Visibility.size() > 0) && (state.Opacity.size() > 0) && (state.AmbientColor.size() > 0) && (state.DiffuseColor.size() > 0) && (state.SpecularColor.size() > 0)); vtkHardwareSelector *selector = renderer->GetSelector(); vtkProperty *property = actor->GetProperty(); vtkCompositeDataDisplayAttributesLegacy* cda = this->CompositeDataDisplayAttributes; // A block always *has* a visibility state, either explicitly set or // inherited. state.Visibility.push( cda->HasBlockVisibility(flat_index) ? cda->GetBlockVisibility(flat_index) : state.Visibility.top()); bool overrides_opacity = cda->HasBlockOpacity(flat_index); if (overrides_opacity) { state.Opacity.push(cda->GetBlockOpacity(flat_index)); } bool overrides_color = cda->HasBlockColor(flat_index); if (overrides_color) { vtkColor3d color = cda->GetBlockColor(flat_index); state.AmbientColor.push(color); state.DiffuseColor.push(color); state.SpecularColor.push(color); } unsigned int my_flat_index = flat_index; // Advance flat-index. After this point, flat_index no longer points to this // block. flat_index++; vtkMultiBlockDataSet *mbds = vtkMultiBlockDataSet::SafeDownCast(dobj); vtkMultiPieceDataSet *mpds = vtkMultiPieceDataSet::SafeDownCast(dobj); if (mbds || mpds) { unsigned int numChildren = mbds? mbds->GetNumberOfBlocks() : mpds->GetNumberOfPieces(); for (unsigned int cc=0 ; cc < numChildren; cc++) { vtkDataObject* child = mbds ? mbds->GetBlock(cc) : mpds->GetPiece(cc); if (child == NULL) { // speeds things up when dealing with NULL blocks (which is common with // AMRs). flat_index++; continue; } this->RenderBlock(renderer, actor, typeflags, forceCompileOnly, child, flat_index, state); } } else if (dobj && state.Visibility.top() == true && state.Opacity.top() > 0.0) { // Implies that the block is a non-null leaf node. // The top of the "stacks" have the state that this block must be rendered // with. if (selector) { selector->BeginRenderProp(); selector->RenderCompositeIndex(my_flat_index); } else { // Not selecting, render the colors and stuff correctly for this block. // For that. this->UpdateRenderingState(renderer->GetRenderWindow(), property, state); } this->DelegatePainter->SetInput(dobj); this->OutputData = dobj; this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly); this->OutputData = 0; if (selector) { selector->EndRenderProp(); } } if (overrides_color) { state.AmbientColor.pop(); state.DiffuseColor.pop(); state.SpecularColor.pop(); } if (overrides_opacity) { state.Opacity.pop(); } state.Visibility.pop(); } //----------------------------------------------------------------------------- void vtkCompositePainter::ReportReferences(vtkGarbageCollector *collector) { this->Superclass::ReportReferences(collector); vtkGarbageCollectorReport(collector, this->OutputData, "Output"); } //---------------------------------------------------------------------------- void vtkCompositePainter::ProcessInformation(vtkInformation* info) { this->Superclass::ProcessInformation(info); if (info->Has(DISPLAY_ATTRIBUTES())) { this->SetCompositeDataDisplayAttributes( vtkCompositeDataDisplayAttributesLegacy::SafeDownCast( info->Get(DISPLAY_ATTRIBUTES()))); } } //---------------------------------------------------------------------------- void vtkCompositePainter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "CompositeDataDisplayAttributes: " ; if (this->CompositeDataDisplayAttributes) { os << endl; this->CompositeDataDisplayAttributes->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } }