<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Hi David,<br><br>There is still something fishy going on. <br><br>While looking at my scene straight from above (the initial view) I calculated the display Z as you said by doing:<br>
<br>Z = (surface - near)/(far - near)<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">and for worldSurface=0, I get the value approx displayZ=0.43. For an arbitrary x,y I then call the display to world transformation in your previous email, and I get e.g.:<br>
<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Display: (303, 298, 0.434) →  World: (0.007, -0.005, 0.272 1.0)<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">
but the worldZ is different from worldSurface=0! Why? I expected a round trip.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">If I now zoom in with the mousewheel (thus I'm still looking from the negative z-direction) and press the mouse button and make another calculation I get:<br>
<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Display: (300 297 0.426) → World: (0.000 -0.000 0.639 1.0)<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">
<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I then get a different value for worldZ. I still expected to get worldSurface=0.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">
Is this a bug, or am I doing something wrong?<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Here the functions (methods):<br><br><pre class=""><span style="color:rgb(160,32,240)">def</span> <span style="color:rgb(0,0,255)">DisplayToWorld</span>(<span style="color:rgb(160,32,240)">self</span>, XYZ):
  <span style="color:rgb(0,139,0)">"""Translate a display XYZ coordinate to a world XYZ coordinate"""</span>
  <span style="color:rgb(160,32,240)">self</span>.renderer.SetDisplayPoint(*XYZ)
  <span style="color:rgb(160,32,240)">self</span>.renderer.DisplayToWorld()
  worldPt = <span style="color:rgb(160,32,240)">self</span>.renderer.GetWorldPoint()
  <span style="color:rgb(160,32,240)">print</span> <span style="color:rgb(0,139,0)">'DisplayToWorld:'</span>,XYZ,<span style="color:rgb(0,139,0)">'->'</span>,worldPt
  <span style="color:rgb(160,32,240)">return</span> worldPt[0]/worldPt[3], worldPt[1]/worldPt[3], worldPt[2]/worldPt[3]

<span style="color:rgb(160,32,240)">def</span> <span style="color:rgb(0,0,255)">WorldZToDisplayZ</span>(<span style="color:rgb(160,32,240)">self</span>, displayXY, worldZ=0):
  <span style="color:rgb(0,139,0)">"""Given a display coordinate displayXY and a worldZ coordinate,</span>
<span style="color:rgb(0,139,0)">  return the corresponding displayZ coordinate"""</span>
  wzNear = <span style="color:rgb(160,32,240)">self</span>.DisplayToWorld(<span style="color:rgb(160,32,240)">list</span>(displayXY) + [0])[2]
  wzFar = <span style="color:rgb(160,32,240)">self</span>.DisplayToWorld(<span style="color:rgb(160,32,240)">list</span>(displayXY) + [1])[2]
  <span style="color:rgb(160,32,240)">return</span> (worldZ-wzNear)/(wzFar-wzNear)</pre>Thanks!<br>Dov<br></div><div style id="divCleekiAttrib"></div><div style id="divCleekiAttrib"></div></div><div class="gmail_extra"><br>
<br><div class="gmail_quote">On Fri, Apr 11, 2014 at 1:08 AM, David Gobbi <span dir="ltr"><<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I should add a bit more explanation to my last email...<br>
<br>
When you move a 3D object with the mouse, you usually want<br>
the exact point on the surface of the object that you pick to be<br>
the point that moves with the mouse.  This means that the<br>
"constraint plane" that you want to use for the motion is the plane<br>
that:<br>
1) contains all the vectors that describe allowed directions of motion, and<br>
2) contains the point on the object that you want to move with the mouse<br>
<br>
In order for the interaction to be intuitive, it is not good enough to use<br>
just any point within the object.  It is necessary to use the point on<br>
the closest surface of the object.<br>
<span class="HOEnZb"><font color="#888888"><br>
   David<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
On Thu, Apr 10, 2014 at 3:45 PM, David Gobbi <<a href="mailto:david.gobbi@gmail.com">david.gobbi@gmail.com</a>> wrote:<br>
> Hi Dov,<br>
><br>
> The DisplayToWorld transformation definitely takes the zoom factor<br>
> into account.  The WorldToDisplay and DisplayToWorld methods are used<br>
> throughout VTK: in the picking, in the interaction, and in the<br>
> rendering.  If they didn't work, then neither would VTK.<br>
><br>
> The only thing in your code that looks questionable to me is that you<br>
> always assume that you world coordinate has Z=0.  Your objects are<br>
> not two dimensional, so obviously when you click on them the "pick"<br>
> position (in world coordinates) will not have Z=0, since the surface<br>
> of the object lies above Z=0.  I believe that the problems that you<br>
> are seeing are due to parallax: the motion at the Z=0 plane is dx,<br>
> but the motion at the surface of your object is in fact slightly higher<br>
> due to perspective.<br>
><br>
> Instead of using Z=0, you should use the actual Z of the surface of<br>
> the object under the cursor.<br>
><br>
>   David<br>
><br>
> On Thu, Apr 10, 2014 at 1:29 AM, Dov Grobgeld <<a href="mailto:dov.grobgeld@gmail.com">dov.grobgeld@gmail.com</a>> wrote:<br>
>> Hi David,<br>
>><br>
>> Though I suspected that the errors are negligible, I changed the code to<br>
>> remember the coordinate at the point of the picking and then translate<br>
>> relative to it. As I expected there was no noticeable difference. The<br>
>> problem at high zooms remain. It appears like the current zoom factor is not<br>
>> taken properly into account the DisplayToWorld transformation. Do you have<br>
>> any idea of what is wrong?<br>
>><br>
>> Thanks,<br>
>> Dov<br>
>><br>
>><br>
>><br>
>><br>
>> On Thu, Apr 10, 2014 at 12:34 AM, David Gobbi <<a href="mailto:david.gobbi@gmail.com">david.gobbi@gmail.com</a>> wrote:<br>
>>><br>
>>> Hi Dov,<br>
>>><br>
>>> I took a quick look at your code, and I notice that on every MouseMove<br>
>>> you compute the dx,dy since the last MouseMove.  I advise that you do<br>
>>> not do this, because it leads to the accumulation of errors.  Instead,<br>
>>> on the ButtonDown, you should save the Display and World coordinates<br>
>>> (i.e. the coordinates at which the drag action started).  Then, in<br>
>>> MouseMove, you should do all your offset calculations relative to this<br>
>>> start position, _not_ relative to the previous MouseMove.  I.e. always<br>
>>> compute dx,dy relative to the position at the start of the drag.<br>
>>><br>
>>>   David<br>
>>><br>
>>> On Wed, Apr 9, 2014 at 2:28 PM, Dov Grobgeld <<a href="mailto:dov.grobgeld@gmail.com">dov.grobgeld@gmail.com</a>><br>
>>> wrote:<br>
>>> > Thanks David. With your help I almost solved the interaction problem. My<br>
>>> > resulting example creates a board with three pieces on it that may be<br>
>>> > moved<br>
>>> > around with the right mouse button. The example may be found here:<br>
>>> ><br>
>>> > <a href="https://gist.github.com/dov/10310484" target="_blank">https://gist.github.com/dov/10310484</a><br>
>>> ><br>
>>> > It gives a very intuitive feeling for moving the pieces around on the<br>
>>> > board<br>
>>> > no matter how the board is rotated. But there is still a dragging<br>
>>> > problem at<br>
>>> > high zoom ins. Then the pieces don't follow the mouse anymore. I'm still<br>
>>> > at<br>
>>> > lost why his happens.<br>
>>> ><br>
>>> > Feel free to add this example to the vtk example programs.<br>
>>> ><br>
>>> > Regards,<br>
>>> > Dov<br>
>>> ><br>
>>> ><br>
>>> ><br>
>>> > On Wed, Apr 9, 2014 at 12:36 AM, David Gobbi <<a href="mailto:david.gobbi@gmail.com">david.gobbi@gmail.com</a>><br>
>>> > wrote:<br>
>>> >><br>
>>> >> Hi Dov,<br>
>>> >><br>
>>> >> When you do the Display-to-World, what are you using as the input "Z"<br>
>>> >> display coordinate? Really, I don't think I understand your situation.<br>
>>> >><br>
>>> >> Generally, if you know that your objects are constrained to move<br>
>>> >> within a certain plane, you should do the following:<br>
>>> >><br>
>>> >> Let X,Y be the "display" coordinates, in pixel units.<br>
>>> >> Let Z be the display "depth", with a range of [0,1].<br>
>>> >><br>
>>> >> Convert display coordinate (X, Y, 0.0) to world coordinate (x_near,<br>
>>> >> y_near, z_near)<br>
>>> >> Convert display coordinate (X, Y, 1.0) to world coordinate (x_far,<br>
>>> >> y_far,<br>
>>> >> z_far)<br>
>>> >><br>
>>> >> Now "far" and "near" define the two ends of a line segment in world<br>
>>> >> coordinates.  These are where the view ray intersects the near and far<br>
>>> >> clipping planes for the vtkCamera.<br>
>>> >><br>
>>> >> At some point along the segment between "near" and "far", the segment<br>
>>> >> will intersect your constraint plane.  Obviously it does not have to<br>
>>> >> be a plane, it can be whatever kind of constraint surface you want.<br>
>>> >> Let's call this intersection point "surface" because it lies on the<br>
>>> >> constraint surface.<br>
>>> >><br>
>>> >> So now you have three points in world coordinates: near, surface, and<br>
>>> >> far.  Use Pythagoras to compute:<br>
>>> >><br>
>>> >> Z = (surface - near)/(far - near)<br>
>>> >><br>
>>> >> Now Z is the depth at which the view ray at (X,Y) intersects your<br>
>>> >> constraint surface.  Of course, maybe you don't need to compute "Z" at<br>
>>> >> all, maybe you can just leave the surface intersection point in world<br>
>>> >> coordinates.<br>
>>> >><br>
>>> >> I don't know if VTK has any special functions to do this, but even if<br>
>>> >> it did, I probably wouldn't use them.  I always write my interaction<br>
>>> >> code by thinking about how the view ray intersects my world space, and<br>
>>> >> then by applying a constraint to achieve the desired 2D-to-3D<br>
>>> >> coordinate conversion (or vice-versa).<br>
>>> >><br>
>>> >>   David<br>
>>> >><br>
>>> >><br>
>>> >><br>
>>> >><br>
>>> >><br>
>>> >><br>
>>> >> On Tue, Apr 8, 2014 at 2:48 PM, Dov Grobgeld <<a href="mailto:dov.grobgeld@gmail.com">dov.grobgeld@gmail.com</a>><br>
>>> >> wrote:<br>
>>> >> > Thanks David,<br>
>>> >> ><br>
>>> >> > I got it to work perfectly as long as I'm looking at the scene from<br>
>>> >> > the<br>
>>> >> > top.<br>
>>> >> > But when i rotate the scene, e.g. tilt it forward around the x-axis,<br>
>>> >> > then<br>
>>> >> > the dragging of the pieces lags behind the mouse. Geometrically I<br>
>>> >> > somehow<br>
>>> >> > understand why, as I'm constraining to only move the piece in the x-y<br>
>>> >> > plane<br>
>>> >> > and the Display2World transformation is also returning a z-component<br>
>>> >> > that<br>
>>> >> > I'm ignoring. Is there a shortcut in vtk to do the necessary z to x,y<br>
>>> >> > projections, or should i just figure it out on my own? Again, my<br>
>>> >> > requirement<br>
>>> >> > is that the mouse should stay around the same position on the piece,<br>
>>> >> > as<br>
>>> >> > I'm<br>
>>> >> > moving it around.<br>
>>> >> ><br>
>>> >> > Regards,<br>
>>> >> > Dov<br>
>>> >> ><br>
>>> >> ><br>
>>> >> ><br>
>>> >> > On Tue, Apr 8, 2014 at 11:19 PM, David Gobbi <<a href="mailto:david.gobbi@gmail.com">david.gobbi@gmail.com</a>><br>
>>> >> > wrote:<br>
>>> >> >><br>
>>> >> >> Hi Dov,<br>
>>> >> >><br>
>>> >> >> I use a function like this:<br>
>>> >> >><br>
>>> >> >> void DisplayToWorld(vtkRenderer *renderer,<br>
>>> >> >>   double x, double y, double z, // window coordinates (the input)<br>
>>> >> >>   double world[3]) // world coordinates (the output)<br>
>>> >> >> {<br>
>>> >> >>   // Use the vtkViewport interterface for conversions.<br>
>>> >> >>   renderer->SetDisplayPoint(x, y, z);<br>
>>> >> >>   renderer->DisplayToWorld();<br>
>>> >> >>   double hcoord[4];<br>
>>> >> >>   renderer->GetWorldPoint(hcoord);<br>
>>> >> >>   world[0] = hcoord[0]/hcoord[3];<br>
>>> >> >>   world[1] = hcoord[1]/hcoord[3];<br>
>>> >> >>   world[2] = hcoord[2]/hcoord[3];<br>
>>> >> >> }<br>
>>> >> >><br>
>>> >> >> It is not enough to have just the xy window coordinates.  You also<br>
>>> >> >> need a z window coordinate, which is a depth value in the range<br>
>>> >> >> [0,1].<br>
>>> >> >> Usually you get the depth from the pick.<br>
>>> >> >><br>
>>> >> >>   David<br>
>>> >> >><br>
>>> >> >><br>
>>> >> >> On Tue, Apr 8, 2014 at 2:03 PM, Dov Grobgeld<br>
>>> >> >> <<a href="mailto:dov.grobgeld@gmail.com">dov.grobgeld@gmail.com</a>><br>
>>> >> >> wrote:<br>
>>> >> >> > I'm trying to create a toy x-y board which has pieces, realized as<br>
>>> >> >> > Actors,<br>
>>> >> >> > that I can drag around in the x-y plane. Through the vtkPicker() I<br>
>>> >> >> > have<br>
>>> >> >> > figured out how to choose a piece, and I can get the render window<br>
>>> >> >> > coordinates through GetInteractor().GetEventPosition(). Further,<br>
>>> >> >> > if I<br>
>>> >> >> > now<br>
>>> >> >> > move the mouse I can calculate a Dx,Dy shift in the window<br>
>>> >> >> > coordinate.<br>
>>> >> >> > But I<br>
>>> >> >> > would now like to translate the Window Dx,Dy to an Actor Dx,Dy<br>
>>> >> >> > shift.<br>
>>> >> >> > I.e. I<br>
>>> >> >> > would like to take a two pairs of xy coordinates in window<br>
>>> >> >> > coordinates<br>
>>> >> >> > and<br>
>>> >> >> > calculate their respective positions in actor coordinates,<br>
>>> >> >> > according<br>
>>> >> >> > to<br>
>>> >> >> > the<br>
>>> >> >> > current actor to dispay matrix. How can I do that?<br>
>>> >> >> ><br>
>>> >> >> > Thanks in advance!<br>
>>> >> >> > Dov<br>
>>> >> ><br>
>>> >> ><br>
>>> ><br>
>>> ><br>
>><br>
>><br>
</div></div></blockquote></div><br></div>