Search code examples
c++vtkqvtkwidget

How to subclass vtkActor


I wanted to be able to access my underlaying data structure when I pick a vtkActor. A class derived from vtkActor holding a ptr to my data structure seemed the easiest approach.

I get the subclass to compile just fine but the actor does not seem to be added to the renderer.

So, here's my class:

//.h
#include <vtkActor.h>
#include <vtkObjectFactory.h>

class Node;

struct Actor : public vtkActor {
    static Actor* New();
    vtkTypeMacro(Actor, vtkActor)

    Node* holding_node;
};

//.cpp
#include "actor.h"
vtkStandardNewMacro(Actor)

In my rendering step: if I instantiate the actor with a vtkActor everything shows up as expected, picking works, etc...

vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();

But no actor is added if I use my Actor class

vtkSmartPointer<Actor>    sphereActor = vtkSmartPointer<Actor>::New();

Nothing else changes in the code. Any ideas of what's wrong?


Solution

  • So, it turns out that there are a bunch of functions that need to be overloaded and a couple touches of macro magic to get this to work.

    I pasted below the example that's working for me now. It is mostly from the vtkFollower code (a derived class from vtkActor). Hope this helps!

        #include <vtkSmartPointer.h>
        #include <vtkRenderer.h>
        #include <vtkObjectFactory.h>
        #include <vtkRenderingCoreModule.h>
        #include <vtkProperty.h>
    
    
        class Node;
    
        class VTKRENDERINGCORE_EXPORT NodeActor : public vtkActor {
            public:
                vtkTypeMacro(NodeActor, vtkActor);
    
             static NodeActor *New();
    
            virtual void ReleaseGraphicsResources(vtkWindow *window) {
                this->Device->ReleaseGraphicsResources(window);
                this->Superclass::ReleaseGraphicsResources(window);
            }
    
            virtual int RenderOpaqueGeometry(vtkViewport *viewport){
                if ( ! this->Mapper ) {
                    return 0;
                }
                if (!this->Property) {
                    this->GetProperty();
                }
                if (this->GetIsOpaque()) {
                    vtkRenderer *ren = static_cast<vtkRenderer *>(viewport);
                    this->Render(ren);
                    return 1;
                }
                return 0;
            }
    
            virtual int RenderTranslucentPolygonalGeometry(vtkViewport *viewport){
                if ( ! this->Mapper ) {
                  return 0;
                }
                if (!this->Property) {
                  this->GetProperty();
                }
                if (!this->GetIsOpaque()) {
                    vtkRenderer *ren = static_cast<vtkRenderer *>(viewport);
                    this->Render(ren);
                    return 1;
                }
                return 0;
            }
    
            virtual void Render(vtkRenderer *ren){
                this->Property->Render(this, ren);
                this->Device->SetProperty (this->Property);
                this->Property->Render(this, ren);
                if (this->BackfaceProperty) {
                    this->BackfaceProperty->BackfaceRender(this, ren);
                    this->Device->SetBackfaceProperty(this->BackfaceProperty);
                }
                if (this->Texture) {
                    this->Texture->Render(ren);
                }
                this->ComputeMatrix();
                this->Device->SetUserMatrix(this->Matrix);
                this->Device->Render(ren,this->Mapper);
            }
    
            void ShallowCopy(vtkProp *prop) {
                NodeActor *f = NodeActor::SafeDownCast(prop);
                this->vtkActor::ShallowCopy(prop);
            }
    
            //****************************************//
            //              my member
            //****************************************// 
            Node*   node_i_represent{nullptr};
    
        protected:
            vtkActor* Device;
    
            NodeActor() {
                this -> Device = vtkActor::New();
            }
    
            ~NodeActor() {
                this -> Device -> Delete();
            }
        private:
    };
    
    vtkStandardNewMacro(NodeActor)