Fwd: Re: User Transform....
David Gobbi
dgobbi at irus.rri.on.ca
Fri Mar 24 07:52:59 EST 2000
Hi Will,
Here is a possible solution. The UserMatrix and UserTransform methods
can both refer to the same transformation.
Inside SetUserTransform(trans), SetUserMatrix(trans.GetMatrixPointer())
is called.
Inside SetUserMatrix(matrix), a new transform 'trans' is created from
the matrix, and SetUserTransform(trans) is called.
Personally, though, I would like the UserMatrix and UserTransform to
be distinct. Why? Because a handfull of VTK classes use the
UserMatrix (e.g. vtkAssembly) which implies that it is not a true
"User" matrix at all... if you set the UserMatrix for an actor and
then add that actor to an assembly, its UserMatrix is overwritten.
It seems that if one calls an ivar "User" and then modifies it when
the user isn't expecting, it should have been called something else.
So, my intention is that the UserTransform will only ever be
set by the user and never be set internally by VTK. And, in
addition, because the UserMatrix _is_ used internally by VTK,
that users should be warned against using it and instructed
to use the UserTransform instead. More power to the user!
Let the user make his/her own actor transforms, instead of
always forcing him/her to use SetPosition(), SetOrigin(),
RotateX(), etc.! (In the paragraph above this one I described
one reason why the UserMatrix is insufficient in this regard).
So far the vtk*Transform additions have resulted in very little
change to existing VTK classes. The following classes have
been modified:
vtkTransform (which remains 100% backwards compatible),
vtkTransformPolyDataFilter - allows perspective & warp transformations
vtkImageReslice - allows warp transformations now
vtkProp3D (plus vtkActor and vtkVolume) - allows transform pipelining
Note that vtkAssembly, vtkLODActor, etc. did not have to be modified
at all. Even the changes to vtkActor and vtkVolume were minor --
a check of UserTransform->GetMTime() was added (a check that, IMHO,
should actually be made in vtkProp3D).
In the future I plan to modify vtkImplicitFunction and vtkTransformFilter
to accept a vtkGeneralTransform in their SetTransform methods (to allow
them to apply nonlinear transforms to their data), and hopefully add a
UserViewTransform and possibly even a UserPerspectiveTransform to
vtkCamera (to give users more control over setting up the camera).
Also note that vtk*Transform classes are almost completely
independant of the rest of VTK... only drastic changes to either
vtkObject or to vtkMatrix4x4 could cause the vtk*Transform classes
themselves to break.
Eeek... this is looking like an opinion piece, and I don't know if
belting out my opinions is wise considering how new I am to VTK.
Oh well, I spent enough time writing this little piece that it would
be a waste to erase it and start over.
- David
--
David Gobbi, MSc dgobbi at irus.rri.on.ca
Advanced Imaging Research Group
Robarts Research Institute, University of Western Ontario
On Fri, 24 Mar 2000, Will Schroeder wrote:
> Hi David-
>
> To add to what Lisa has said, I have some concern about what appears to be
> overlapping functionality. My experience is that such overlaps result in
> misbehaving code, or overly complex code, or code that is hard to explain
> in a rational way to a user. In addition, I have over 60 files modified
> right now due to a complete rewrite of picking, I'm not sure what to make
> of yet another "matrix" in the rendering process. Also, having been through
> this picking rewrite, I'm concerned about the complexity of the rendering
> process, it's getting out of hand.
>
> Bottom line - I'd like to see if we can't unify this implementation, either
> by eliminating UserMatrix, or modifying UserMatrix to accept a different
> type and changing the API, etc.
>
> Will
>
> From David-
> >The UserTransform serves the same purpose as the UserMatrix.
> >That much is obvious, so here is why just doing
> >actor->SetUserMatrix(transform->GetMatrixPointer())
> >is different from doing
> >actor->SetUserTransform(transform):
> >
> >
> >The new set of transforms that I've implemented are pipelined.
> >When you call transform->TransformPoint(inPoint,outPoint)
> >or transform->TransformPoints(inPoints,outPoints)
> >the class first calls its 'Update()' method before proceeding.
> >
> >
> >The vtkTransform::Update() method is empty, but e.g.
> >vtkLandmarkTransform::Update() uses this->SourceLandmarks
> >and this->TargetLandmarks to make a 4x4 registration matrix.
> >The vtkLinearTransformConcatenation::Update() method looks at
> >its list of transforms and concatenates all their matrices.
> >
> >
> >
> >So, the reason that actor->SetUserMatrix(transform->GetMatrixPointer())
> >is insufficient is that it 'breaks the pipeline', i.e. the matrix
> >will only be updated if the user explicitly calls Update() on the
> >transform.
> >
> >
> >
> >For example, in my lab we have a vtkFlockTracker class that interfaces
> >to the Flock of birds. We want to get a transform from the flock,
> >apply various calibrations, and then pass the result on to an actor.
> >
> >
> > flockTracker
> > |
> > v
> > calibrationTrans1 flockTrans calibrationTrans2
> > | | |
> > | v |
> > \--> concatenationTrans <--/
> > |
> > v
> > flockActor->SetUserTransform()
> >
> >
> >I'm not sure how clear the diagram is, but the idea is that when
> >flockActor needs do 'do its stuff,' it calls calibrationTrans->GetMatrix()
> >which (internally) calls calibrationTrans->Update() which causes
> >calibrationTrans1, flockTrans, and calibrationTrans2 to be concatenated.
> >
> >
> >
> >So, to make a long story short, back a couple years ago when I started
> >using VTK the data pipeline made a lot of sense... but I really wished
> >that I could pipeline operations on transforms as well. It wasn't
> >until a few months ago that I started actually writing the code.
> >
> >
> > - David
>
>
> At 05:13 PM 3/23/2000 -0500, you wrote:
> >Hi Lisa,
> >
> >This sounds like an option - make vtkMatrix4x4 a data object.
> >Unfortunately vtkRenderWindowInteractor and probably other classes
> >abuse the UserMatrix i.e. modify it directly and completely
> >disregard the fact that it might be part of vtkTransform much
> >less part of a pipeline.
> >
> >There are a couple reasons why I started from scratch in developing
> >the transform pipeline instead of using existing VTK mechanisms:
> >1) Efficiency, both speed & memory usage
> >2) Simplicity - e.g. the vtkGeneralTransformConcatenation acts as both
> > filter & data in one. This cuts down the number of lines of code
> > needed to both implement the class & to use it.
> >3) Flexibility - only a subset of the vtk*Transforms use a vtkMatrix4x4,
> > e.g. the vtkThinPlateSplineTransform obviously could not use a
> > vtkMatrix4x4.
> >
> >I actually have a class (not contributed yet) which will allow you
> >to convert a vtkMatrix4x4 object into a vtkLinearTransform object.
> >If the vtkMatrix4x4 was a data object, then it would be possible to
> >go the other way as well.
> >
> >
> >So, in conclusion: I think that converting the transform pipeline
> >into a data+filter pipeline would both add complication to and
> >reduce the flexibility the transform pipeline. Being able to do
> >
> > trans = vtkTransform()
> > invtrans = trans.GetInverse()
> >
> >is a much tidier way of getting a pipelined transform inverse than
> >
> > trans = vtkTransform()
> >
> > inverse = vtkTransformInverse()
> > inverse.SetInput(trans.GetOutput())
> >
> > invmatrix = inverse.GetOutput()
> >
> >However, having vtkMatrix4x4 as a data object could be a good thing.
> >
> > - David
> >
> >P.S. Is this list new? A vtk-developers list is really a good idea.
> >
> >--
> > David Gobbi, MSc dgobbi at irus.rri.on.ca
> > Advanced Imaging Research Group
> > Robarts Research Institute, University of Western Ontario
> >
> >On Thu, 23 Mar 2000, Lisa Sobierajski Avila wrote:
> >
> > > Hello David,
> > >
> > > I see what you are trying to do, and I was faced with the same problem at
> > > one point with vtkPiecewiseFunction - I needed it to be an output of
> > > something and work in a pipeline. The solution I took in that case was to
> > > make vtkPiecewiseFunction a subclass of vtkDataObject. That was an ok
> > > solution there, but wouldn't work (with vtk "as is") for you since
> > > vtkDataObject is pretty heavy weight.
> > >
> > > Here is a suggestion I have (and I throw this out to everyone on
> > vtkdevelop
> > > for comment). I would like to make vtkDataObject as light weight as
> > > possible - remove most of the ivars. Then create a new subclass with those
> > > ivars back in it, and vtkDataSet would be a subclass of this new class.
> > > vtkMatrix4x4, vtkPiecewiseFunction, and whatever else needs to be would be
> > > subclasses of vtkDataObject. This way you could do
> > > actor->SetUserMatrix(yourfilter->GetOutput()) where the GetOutput() method
> > > of your filter would return a vtkMatrix *. vtkMatrix would be modified to
> > > call Update() on its source when necessary (or do nothing if its source is
> > > NULL) With these changes you could remove the SetUserTransform from
> > vtkProp3D.
> > >
> > > I'll probably go ahead and try this out in the next few days to see how it
> > > works out. It will take a bit of thought to determine how much
> > > functionality to provide - the basic data object won't support
> > streaming so
> > > it won't need to store any extent / pieces information and it won't
> > support
> > > data releasing, but can a vtkMatrix4x4 move across a input/output port?
> > Not
> > > that the ports are back in yet - but they will be soon....
> > >
> > >
> > > Lisa
> > >
> > >
> > >
> > >
> > > At 03:17 PM 3/22/00, you wrote:
> > > >The answer to the UserTransform ivar in vtkProp3D. I'm studying this to
> > > >see what impact it has on the picking.
> > > >Will
> > > >
> > > > >Date: Wed, 22 Mar 2000 14:55:50 -0500 (EST)
> > > > >From: David Gobbi <dgobbi at irus.rri.on.ca>
> > > > >X-Sender: dgobbi at localhost.localdomain
> > > > >To: Will Schroeder <will.schroeder at kitware.com>
> > > > >Subject: Re: User Transform....
> > > > >
> > > > >Hi Will,
> > > > >
> > > > >The UserTransform serves the same purpose as the UserMatrix.
> > > > >That much is obvious, so here is why just doing
> > > > >actor->SetUserMatrix(transform->GetMatrixPointer())
> > > > >is different from doing
> > > > >actor->SetUserTransform(transform):
> > > > >
> > > > >The new set of transforms that I've implemented are pipelined.
> > > > >When you call transform->TransformPoint(inPoint,outPoint)
> > > > >or transform->TransformPoints(inPoints,outPoints)
> > > > >the class first calls its 'Update()' method before proceeding.
> > > > >
> > > > >The vtkTransform::Update() method is empty, but e.g.
> > > > >vtkLandmarkTransform::Update() uses this->SourceLandmarks
> > > > >and this->TargetLandmarks to make a 4x4 registration matrix.
> > > > >The vtkLinearTransformConcatenation::Update() method looks at
> > > > >its list of transforms and concatenates all their matrices.
> > > > >
> > > > >
> > > > >So, the reason that actor->SetUserMatrix(transform->GetMatrixPointer())
> > > > >is insufficient is that it 'breaks the pipeline', i.e. the matrix
> > > > >will only be updated if the user explicitly calls Update() on the
> > > > >transform.
> > > > >
> > > > >
> > > > >For example, in my lab we have a vtkFlockTracker class that interfaces
> > > > >to the Flock of birds. We want to get a transform from the flock,
> > > > >apply various calibrations, and then pass the result on to an actor.
> > > > >
> > > > > flockTracker
> > > > > |
> > > > > v
> > > > > calibrationTrans1 flockTrans calibrationTrans2
> > > > > | | |
> > > > > | v |
> > > > > \--> concatenationTrans <--/
> > > > > |
> > > > > v
> > > > > flockActor->SetUserTransform()
> > > > >
> > > > >I'm not sure how clear the diagram is, but the idea is that when
> > > > >flockActor needs do 'do its stuff,' it calls
> > calibrationTrans->GetMatrix()
> > > > >which (internally) calls calibrationTrans->Update() which causes
> > > > >calibrationTrans1, flockTrans, and calibrationTrans2 to be concatenated.
> > > > >
> > > > >
> > > > >So, to make a long story short, back a couple years ago when I started
> > > > >using VTK the data pipeline made a lot of sense... but I really wished
> > > > >that I could pipeline operations on transforms as well. It wasn't
> > > > >until a few months ago that I started actually writing the code.
> > > > >
> > > > > - David
> > > > >
> > > > >
> > > > >P.S. In general I've been working on this more-or-less independently
> > > > > and with little feedback, perhaps most VTK users simply don't
> > > > > work with transforms much or take viewpoint that 'it's nice, but
> > > > > can't you do that already with assemblies?' Not that lack
> > > > > of feedback would ever keep me from monkeying around with VTK
> > > > > as long as I have CVS access...
> > > > >
> > > > >--
> > > > > David Gobbi, MSc dgobbi at irus.rri.on.ca
> > > > > Advanced Imaging Research Group
> > > > > Robarts Research Institute, University of Western Ontario
> > > > >
> > > > >On Wed, 22 Mar 2000, Will Schroeder wrote:
> > > > >
> > > > > >
> > > > > > Hi David-
> > > > > >
> > > > > > Can you help me here? The UserTransform, how do you use and
> > what's it
> > > > for?
> > > > > >
> > > > > > Will
> > > > > >
> > >
> > >
>
More information about the vtk-developers
mailing list