Where Sun always shine...

 Strange Engine mini API

Please have a look also to my on-going documentation work: Strange Engine Documentation page.

Introduction

Beginning with version 1.00 alpha Build 6, Strange Engine provides a COM plug-in interface for custom made Backprojectors.
Users can write their own ActiveX plug-in components and use them for backprojection of a collection of projections to a volume.
 
 


The IBackProjectorRenderer interface

The plug-in you have to write has to support the Strange Engine IBackProjectorRenderer COM interface.
You have basically two ways of writing the plug-in: MFC or ATL. Both are supported by the Microsoft Visual C++ IDE.

The IBackprojector interface as of writing (please remember that this is an alpha release and is subjected to major changes in the future) consists of three simple functions.

interface IBackProjectorRenderer : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE BackProjectPhantom(
            /* [in] */ IBackProjector *pIBackProjector,
            /* [in] */ IPhantom *pIPhantom,
            /* [in] */ IVolume *pIVolume) = 0;

        virtual HRESULT STDMETHODCALLTYPE BackProjectProjection(
            /* [in] */ IBackProjector *pIBackProjector,
            /* [in] */ IProjection *pIProjection,
            /* [in] */ IVolume*pIVolume) = 0;

        virtual HRESULT STDMETHODCALLTYPE BackProjectProjectionCollection(
            /* [in] */ IBackProjector *pIBackProjector,
            /* [in] */ IProjectionCollection *pIProjectionCollection,
            /* [in] */ IVolume *pIVolume) = 0;
    };

The first function, BackProjectPhantom, while defined is not currently supported so for the moment just ignore it.
The second function, BackProjectProjection, is called by a Backprojector to render into a Volume, as passed as IVolume interface pointer, a single Projection.
If your backprojection method is smart enough to speed up backprojection by exploiting groupal properties, ignore BackProjectProjection and implement only BackProjectProjectionCollection. This function asks for the backprojection of the entire collection of projections.
 

The IBackProjector interface

You should have noted that each of the three methods of the IBackProjectorRenderer interface is passed a pointer to a IBackProjector interface.
Here is the definition of this COM interface:

interface IBackProjector : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE SetComputation(
            /* [in] */ int ComputationSteps,
            /* [in] */ const BSTR DisplayStringWhileComputing) = 0;

        virtual HRESULT STDMETHODCALLTYPE StepComputation( void) = 0;
    };

These two methods are used by Strange Engine to display messages in the Backprojector status bar while the rendering is progressing. Moreover by calling the SetComputation/StepComputation pair you makes also possible for Strange Engine to compute rendering times which are reported at the end of the computation.
 

The IVolume interface

The IVolume interface provides all the data you need to gather information about the volume you're going to render.

interface IVolume : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE GetVoxelGeometry(
            /* [out] */ float *DimX,
            /* [out] */ float *DimY,
            /* [out] */ float *DimZ,
            /* [out] */ float *MinX,
            /* [out] */ float *MinY,
            /* [out] */ float *MinZ,
            /* [out] */ float *MaxX,
            /* [out] */ float *MaxY,
            /* [out] */ float *MaxZ,
            /* [out] */ float *StepX,
            /* [out] */ float *StepY,
            /* [out] */ float *StepZ,
            /* [out] */ int  *NumX,
            /* [out] */ int  *NumY,
            /* [out] */ int  *NumZ) = 0;

        virtual HRESULT STDMETHODCALLTYPE GetDataPointer(
            /* [out] */ float *pData) = 0;
    };

The GetVoxelGeometry method is used by the IBackProjectorRenderer implementer to get information about the volume geometry.
GetDataPointer returns a linear float* pointer in which to write calculated voxel values.
 

The IProjection and IProjectionCollection interfaces

IProjection provides all the information you need to access projection data. If you are implementing the BackProjectProjectionCollection method you have also to use IProjectionCollection in order to enumerate projections.

interface IProjectionCollection : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE GetHomogeneity(
            /* [out] */ BOOL *IsHomogeneous) = 0;

        virtual HRESULT STDMETHODCALLTYPE GetCount(
            /* [out] */ int *pProjectionCount) = 0;

        virtual HRESULT STDMETHODCALLTYPE GetAt(
            /* [in] */ int Position,
            /* [out] */ IListElementStub *pIListElementStub) = 0;
    };

IsHomogeneous checks if the given collection is made of similar (i.e. with same dimensions and pixel number) projections. As of now returns always TRUE.
GetCount returns the number of projections, while GetAt returns a Stub interface to the projection in the given Position.
Stub interfaces are used to load and offload projections from memory.

interface IListElementStub : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE Load( void) = 0;

        virtual HRESULT STDMETHODCALLTYPE OffLoad( void) = 0;
    };

Call Load before using the projection and OffLoad after you have done processing it (so Strange Engine can free some memory). You can get a IProjection pointer by QueryInterface on the IListElementStub interface.

interface IProjection : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE GetRasterGeometry(
            /* [out] */ float *DimX,
            /* [out] */ float *DimY,
            /* [out] */ float *MinX,
            /* [out] */ float *MinY,
            /* [out] */ float *MaxX,
            /* [out] */ float *MaxY,
            /* [out] */ float *StepX,
            /* [out] */ float *StepY,
            /* [out] */ int *NumX,
            /* [out] */ int *NumY) = 0;

        virtual HRESULT STDMETHODCALLTYPE GetSourcePosition(
            /* [out] */ float *x,
            /* [out] */ float *y,
            /* [out] */ float *z) = 0;

        virtual HRESULT STDMETHODCALLTYPE GetDetectorCenterPosition(
            /* [out] */ float *x,
            /* [out] */ float *y,
            /* [out] */ float *z) = 0;

        virtual HRESULT STDMETHODCALLTYPE GetDetectorTrajectoryMatrix(
            /* [out] */ double m[ 16 ]) = 0;

        virtual HRESULT STDMETHODCALLTYPE GetDataPointer(
            /* [out] */ float *pData) = 0;
    };

All methods should be self-explaining. The 4 x 4 matrix provided by GetDetectorTrajectoryMatrix describes the matrix used by the system to generate the trajectory of the detector. Please note that currently Strange Engine generates ONLY trajectories of kind circle-on-xz. In the future interface changes to support more elaborate trajectories are very likely.
 

Property Pages

Strange Engine also supports ActiveX property pages.The BackProjector window automatically adds them to its view whenever a property-page capable plug-in is selected. The management of property pages is your job. Have a look at my Agofdk plug-in to understand how property pages can enhance your plug-ins.
 

A word about CATIDs

Beginning with Build 6, Strange Engine supports Component Categories. This feature requires Windows NT 4 SP 3 or Windows 2000.
The plug-ins you write HAS always to declare themselves, during self-registration, as supporting IStrangeEnginePlugin CATID which is defined in CATTypes.c even if you plan to use previous versions of Windows NT 4.
I suggest moreover to install your plug-ins in Strange Engine / Plugins directory. If you don't do this your plug-ins will not be found in previous versions of Windows NT 4

The FDK example

Strange Engine is provided with two fully functional ActiveX plug-ins.
Agofdk offers fast Feldkamp backprojection through a pretty property page interface.
Fdk is a vanilla Feldkamp backprojector. Source code is available, so you can use it as a starting point for realizing your own ActiveX plug-ins.
While Fdk is currently written using MFC, I plan in the future to release an ATL version.

Download

If you are interested in developing a custom Strange Engine plug-in please download the Strange Engine SDK distribution.
The SDK contains:
  1. COMTypes_i.c
  2. CATTypes.c
  3. COMTypes.h
  4. COMTypes.idl
  5. Fdk plug-in source code
  6. Agofdk plug-in

Stefano Agostinelli - agostinellis@bigfoot.com

This page hosted by  Get your own Free Home Page

1