[vtkusers] vtkWin32VideoSource shows no output when used in conjunction with vtkTextActor3D

Rhys Thomas eep22f at bangor.ac.uk
Thu Jul 17 06:00:04 EDT 2008


Hello vtkusers,

I have been experiencing problems whilst using vtkTextActor3D. My 
application should display an image from a vtkWin32VideoSource in the 
background (from a webcam) with a combination of different 
vizualisations on top. I use a combination of volume data (vtkVolume), 
polydata, arrows (using vtkArrowSource) and text (using vtkTextActor3D). 
As well as displaying the data the data is rotated. This is achieved by 
placing all of the components into a vtkAssembly. When I compile the 
code without enabling the text the desired result is produced, however 
when the text is enabled everything apart from the video is displayed on 
top of a white background (on machine 1), or on an alternating black and 
white background (machine 2).

Machine 1 has an Intel P4 processor and an nVidia 8800GTX graphics card, 
running windows xp and Visual Studio 2005. Machine 2 is an Acer laptop 
with an AMD TL-52 processor and an ATI mobility Radeon graphics card, 
running windows xp MCE and Visual Studio 2005 Express Edition. Both 
machines have vtk version 5.04 installed.

I have included the source code for the application below. The line 
"#define _TEXT_" can be commented/uncommented to turn the text on and 
off, and the line "#define _VIDEO_" can be used to commented/uncommented 
to turn the video feed on and off. Is this problem a result of my 
coding, or because of the experimental nature of vtkTextActor3D?

#include <vtkPolyData.h>
#include <vtkRenderer.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyDataReader.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkVolume.h>
#include <vtkAssembly.h>
#include <vtkVolumeTextureMapper3D.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkProperty.h>
#include <vtkCommand.h>
#include <vtkArrowSource.h>
#include <vtkTextActor3D.h>
#include <vtkTextProperty.h>
#include <vtkSphereSource.h>
#include <vtkWin32VideoSource.h>
#include <vtkImageMapper.h>
#include <vtkActor2D.h>
#include <vtkProperty2D.h>
#include <vtkCamera.h>
#include <vtkImageResample.h>
#include <vtkOutputWindow.h>

#define OPACITY_DELTA 0.00125
//#define _ACTOR_
#define _TEXT_
#define _VIDEO_

vtkRenderWindowInteractor *iren;
vtkPiecewiseFunction *transparency;
vtkAssembly *assembly;
vtkVolumeProperty *volProperty;
vtkRenderWindow *renWin;
vtkProp3D *textPointer;
vtkProp3D *textPointer2;
vtkAssembly *aqueduct;
double opacityLevel;
double opacityDelta;
bool changeTransparency;

vtkWin32VideoSource *webcam;
vtkImageMapper *camMapper;
vtkActor2D *camActor;

/**
    Time dependant operations. Was initially used to change transparency 
with
    time (hence the name). Now rotates the assembly and grabs a camera 
frame.
*/
class TransparencyChanger : public vtkCommand
{
public:
    static TransparencyChanger *New()
    {return new TransparencyChanger;}
    virtual void Execute(vtkObject *caller, unsigned long, void *)
    {
        if(changeTransparency)
        {
            webcam->Grab();
            /**
                Reverse the direction of change of opacity if either 
zero or one
                have been reached.
            */
    /*        if((opacityLevel <= 0) || (opacityLevel >= 0.125))
            {
                opacityDelta *= -1;
            }
            opacityLevel += opacityDelta;*/
            transparency->RemovePoint(3);
            transparency->RemovePoint(255);
            //transparency->AddSegment(2, opacityLevel, 255, opacityLevel);
            transparency->AddPoint(3, opacityLevel);
            transparency->AddPoint(255, opacityLevel);
        //    assembly->RotateX(0.1);
        //    cout << ".";
        //    cout << opacityLevel << "\r";
        //    assembly->Modified();
            assembly->RotateY(1);
            textPointer->RotateY(1);
            textPointer2->RotateY(1);
            aqueduct->RotateY(-1);
            renWin->Render();
            iren->CreateTimer(VTKI_TIMER_UPDATE);
        }
    }
};

/**
    Attempts to reset the vtk timer. Also gives feedback to the user about
    what events have been generated.
*/
class TimerResetter : public vtkCommand
{
public:
    static TimerResetter *New()
    {return new TimerResetter;}
    virtual void Execute(vtkObject *caller, unsigned long eventId, void *)
    {
        cout << "Event" << eventId << endl;
        if(eventId == vtkCommand::ModifiedEvent)
        {
            cout << "Modified Event" << endl;
        }
        if(eventId == vtkCommand::StartEvent)
        {
            cout << "Start Event" << endl;
        }
        if(eventId == vtkCommand::DeleteEvent)
        {
            cout << "Delete Event" << endl;
        }
        if(eventId == vtkCommand::LeftButtonPressEvent)
        {
            cout << "Left Mouse Button Pressed" << endl;
        }
        iren->CreateTimer(VTKI_TIMER_UPDATE);
    }
};

/**
    Catches key events and processes them appropriately.
*/
class myVTKKeyboardCallback : public vtkCommand
{
public:
    static myVTKKeyboardCallback *New()
    {return new myVTKKeyboardCallback;}
    virtual void Execute(vtkObject *caller, unsigned long, void *)
    {
        char keyPressed =
            vtkRenderWindowInteractor::SafeDownCast(caller)->GetKeyCode();
        /**
            The escape key. Exit the program if this is pressed.
        */
        //cout << keyPressed << endl;
        if(keyPressed == 27)
        {
            iren->Disable();
            iren->TerminateApp();
        //    cout << "Exit Event";
        }
        /**
            Toggle whether or not the transparency changes with time.
        */
        //if(keyPressed == 97)//The 'T' key
        //{
        //    changeTransparency = !changeTransparency;
        //    iren->ReInitialize();
        //}
        /**
            Change the opacity of the volume data making the polydata 
more or
            less visible.
        */
        if(keyPressed == ']')
        {
            if(opacityLevel > 0)
            {
                opacityLevel += OPACITY_DELTA;
                cout << "Up" << endl;
                renWin->Render();
            }
        }
        if(keyPressed == '[')
        {
            if(opacityLevel < 0.25)
            {
                opacityLevel -= OPACITY_DELTA;
                renWin->Render();
            }
        }
    }
};

void main(int argc, char **argv)
{
    vtkOutputWindow::GetInstance()->PromptUserOn();
    /**
        Set up pipeline for polydata.
    */
    vtkPolyDataReader *polyReader = vtkPolyDataReader::New();
    polyReader->SetFileName("C:\\JDHead\\VentriclesPoly.vtk");
    //polyReader->SetFileName("VentriclesPoly.vtk");
    polyReader->Update();
    vtkPolyData *ventricles = polyReader->GetOutput();
    vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
    mapper->SetInput(ventricles);
    vtkActor *actor = vtkActor::New();
    actor->SetMapper(mapper);
    vtkProperty *ventProperty = vtkProperty::New();
    ventProperty->SetColor(1.0, 0, 0);
    ventProperty->SetDiffuseColor(1.0, 0.0, 0.0);
    ventProperty->SetSpecular(0);
//    ventProperty->SetSpecularPower(20);
    ventProperty->SetSpecularColor(0.75, 0.75, 0.75);
    ventProperty->SetOpacity(1.0);
    actor->SetProperty(ventProperty);

    /**
        Set up pipeline for volume data.
    */
    vtkStructuredPointsReader *structReader = 
vtkStructuredPointsReader::New();
    structReader->SetFileName("C:\\JDHead\\JDHead_8.vtk");
    //structReader->SetFileName("JDHead_8.vtk");
    structReader->Update();
    vtkStructuredPoints *points = structReader->GetOutput();
    vtkVolumeTextureMapper3D *volMap = vtkVolumeTextureMapper3D::New();
    volMap->SetInput(points);
    vtkVolume *volume = vtkVolume::New();
    volume->SetMapper(volMap);
    opacityLevel = 0.01;
    opacityDelta = OPACITY_DELTA;
    transparency = vtkPiecewiseFunction::New();
    transparency->AddSegment(0, 0, 2, 0);
//    transparency->AddSegment(2, 0.01, 255, 0.01);
    transparency->AddPoint(3, opacityLevel);
    transparency->AddPoint(255, opacityLevel);

    /**
        We want a transparent volume so that we can see the polydata 
located
        within.
    */
    volProperty = vtkVolumeProperty::New();
    volProperty->SetScalarOpacity(transparency);
    volume->SetProperty(volProperty);

    vtkColorTransferFunction *rescaleGrey = vtkColorTransferFunction::New();
    rescaleGrey->AddRGBSegment(0.0, 0.0, 0.0, 0.0, 255.0, 1.0, 1.0, 1.0);
    volProperty->SetColor(rescaleGrey);

    /**
        Set up pipeline for arrow. Use only one arrow, supplied to three 
different
        actors, each with a different position, orientation and scale.
    */
    vtkArrowSource *arrow = vtkArrowSource::New();
    arrow->SetTipResolution(20);
    arrow->SetShaftResolution(20);
    vtkPolyData *arrowData = arrow->GetOutput();
    vtkPolyDataMapper *arrowMapper = vtkPolyDataMapper::New();
    arrowMapper->SetInput(arrowData);
    vtkActor *arrowActor = vtkActor::New();
    arrowActor->SetMapper(arrowMapper);
    vtkProperty *arrowProperty = vtkProperty::New();
    arrowProperty->SetDiffuseColor(0.0, 1.0, 0.0);
    arrowActor->SetProperty(arrowProperty);
    arrowActor->SetScale(150);
    arrowActor->SetPosition(30, 192, 110);   

    vtkActor *arrow2Actor = vtkActor::New();
    arrow2Actor->SetMapper(arrowMapper);
    arrow2Actor->SetScale(150);
    arrow2Actor->SetProperty(arrowProperty);
    arrow2Actor->SetPosition(430, 230, 110);
    arrow2Actor->RotateY(180);

    vtkActor *arrow3Actor = vtkActor::New();
    arrow3Actor->SetMapper(arrowMapper);
    arrow3Actor->SetScale(300, 50, 50);
    arrow3Actor->SetPosition(92, 410, 260);
    arrow3Actor->SetProperty(arrowProperty);
    arrow3Actor->RotateY(45);
    arrow3Actor->RotateZ(-45);

    /**
        Set up pipeline for 3D text. All text components here have the same
        properties.
    */
    vtkTextActor3D *text = vtkTextActor3D::New();
    text->SetInput("Third Ventricle");
    vtkTextProperty *textProperty = vtkTextProperty::New();
    textProperty->SetColor(0.0, 1.0, 0.0);
    textProperty->BoldOn();
    text->SetTextProperty(textProperty);
    text->SetPosition(30, 180, 110);
    text->RotateY(180);
    text->RotateZ(180);
    text->SetScale(2);
    textPointer = text;

    vtkTextActor3D *text2 = vtkTextActor3D::New();
    text2->SetInput("Fourth Ventricle");
    text2->SetTextProperty(textProperty);
    text2->SetPosition(430, 218, 110);
    text2->RotateZ(180);
    text2->RotateY(180);
    text2->SetScale(2);
    textPointer2 = text2;

    vtkTextActor3D *text3 = vtkTextActor3D::New();
    text3->SetInput("Cerebral Aqueduct");
    text3->SetTextProperty(textProperty);
    text3->SetScale(2);
    text3->RotateX(180);
    text3->SetPosition(92, 410, 260);
    text3->RotateY(180);
   
    /**
        Set up combined part of the vtk pipeline.
    */
    assembly = vtkAssembly::New();
    assembly->AddPart(actor);
    assembly->AddPart(volume);
    assembly->AddPart(arrowActor);
    assembly->AddPart(arrow2Actor);
    assembly->RotateX(180);
    assembly->SetOrigin(192, 192, 110);
    assembly->SetPosition(192, 192, 110);

    aqueduct = vtkAssembly::New();
    aqueduct->AddPart(arrow3Actor);
    aqueduct->SetOrigin(240, 200, 110);
    assembly->AddPart(aqueduct);
    aqueduct->RotateY(180);

#ifdef _TEXT_
    assembly->AddPart(text);
    assembly->AddPart(text2);
    aqueduct->AddPart(text3);
#endif

    cout << assembly->GetEstimatedRenderTime() << endl;

    /**
        Setup pipeline to capture video from our webcam.
    */
    webcam = vtkWin32VideoSource::New();
    webcam->SetFrameSize(640, 480, 1);
    webcam->SetOutputFormat(VTK_RGB);
    webcam->SetFrameRate(15.0);
    //webcam->VideoFormatDialog();
    camMapper = vtkImageMapper::New();
    vtkImageResample *resample = vtkImageResample::New();
    resample->SetInput(webcam->GetOutput());
    resample->SetAxisOutputSpacing(0, 0.5);
    resample->SetAxisOutputSpacing(1, 0.46875);
    camMapper->SetInput(resample->GetOutput());
    //camMapper->SetInput(webcam->GetOutput());
    camMapper->SetColorLevel(127.5);
    camMapper->SetColorWindow(255);
    camMapper->SetZSlice(0);
    camActor = vtkActor2D::New();
    camActor->SetMapper(camMapper);
    vtkRenderer *camRenderer = vtkRenderer::New();
    camRenderer->AddActor(camActor);

    vtkRenderer *renderer = vtkRenderer::New();

#ifdef _ACTOR_
    renderer->AddActor(actor);
#else
    renderer->AddActor(assembly);
#endif
//    renderer->EraseOff();
    camRenderer->EraseOff();
    renderer->SetBackground(1.0, 1.0, 1.0);
    renWin = vtkRenderWindow::New();
    renWin->SetNumberOfLayers(2);
#ifdef _VIDEO_
    renWin->AddRenderer(camRenderer);
#endif
    renWin->AddRenderer(renderer);
    renderer->SetLayer(1);
    camRenderer->SetLayer(0);
//    camRenderer->InteractiveOff();
    renWin->SetSize(1280, 1024);
    renWin->FullScreenOn();
    renWin->SetStereoTypeToCrystalEyes();
    //    camActor->SetWidth(1);
    //    camActor->SetHeight(1);
    //    renderer->SetAllocatedRenderTime(0.25);
    //    camRenderer->SetAllocatedRenderTime(0.25);

    /**
        Set up interaction. The timer controls frame grabbing and 
rotation of
        the assembly.
    */
    iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);
    myVTKKeyboardCallback *keyed = myVTKKeyboardCallback::New();
    iren->AddObserver(vtkCommand::KeyPressEvent, keyed, 1);
    TransparencyChanger *changer = TransparencyChanger::New();
    iren->AddObserver(vtkCommand::TimerEvent, changer, 1);
    TimerResetter *resetter = TimerResetter::New();
    iren->AddObserver(vtkCommand::LeftButtonPressEvent, resetter, 0);
    changeTransparency = true;
    iren->Initialize();
    iren->CreateTimer(VTKI_TIMER_FIRST);
    iren->Start();

    polyReader->Delete();
    structReader->Delete();
//    ventricles->Delete();
//    points->Delete();
    mapper->Delete();
    actor->Delete();
    renderer->Delete();
    renWin->Delete();
    iren->Delete();
}

Many Thanks

Rhys Thomas

-- 
Mr. Rhys Thomas
School of Computer Science
Bangor University
http://www.cs.bangor.ac.uk/


-- 
Gall y neges e-bost hon, ac unrhyw atodiadau a anfonwyd gyda hi,
gynnwys deunydd cyfrinachol ac wedi eu bwriadu i'w defnyddio'n unig
gan y sawl y cawsant eu cyfeirio ato (atynt). Os ydych wedi derbyn y
neges e-bost hon trwy gamgymeriad, rhowch wybod i'r anfonwr ar
unwaith a dilëwch y neges. Os na fwriadwyd anfon y neges atoch chi,
rhaid i chi beidio â defnyddio, cadw neu ddatgelu unrhyw wybodaeth a
gynhwysir ynddi. Mae unrhyw farn neu safbwynt yn eiddo i'r sawl a'i
hanfonodd yn unig  ac nid yw o anghenraid yn cynrychioli barn
Prifysgol Bangor. Nid yw Prifysgol Bangor yn gwarantu
bod y neges e-bost hon neu unrhyw atodiadau yn rhydd rhag firysau neu
100% yn ddiogel. Oni bai fod hyn wedi ei ddatgan yn uniongyrchol yn
nhestun yr e-bost, nid bwriad y neges e-bost hon yw ffurfio contract
rhwymol - mae rhestr o lofnodwyr awdurdodedig ar gael o Swyddfa
Cyllid Prifysgol Bangor.  www.bangor.ac.uk

This email and any attachments may contain confidential material and
is solely for the use of the intended recipient(s).  If you have
received this email in error, please notify the sender immediately
and delete this email.  If you are not the intended recipient(s), you
must not use, retain or disclose any information contained in this
email.  Any views or opinions are solely those of the sender and do
not necessarily represent those of the Bangor University.
Bangor University does not guarantee that this email or
any attachments are free from viruses or 100% secure.  Unless
expressly stated in the body of the text of the email, this email is
not intended to form a binding contract - a list of authorised
signatories is available from the Bangor University Finance
Office.  www.bangor.ac.uk




More information about the vtkusers mailing list