vtk translation, rotation, connecting MFC problem summary (expanding VTK to MFC, the idea is very good)

Recently, I am writing a program with vtk+MFC. Because I am a beginner to learn vtk, I have implemented some functions according to the example of vtk, but there are several problems that have deeply puzzled me, and I have not been able to solve it for a long time. Searched the web and couldn't find any examples. I finally solved it today and sent it out for everyone to learn together.

1. vtk provides an interaction style (vtkInteractionStyle), but the encapsulation is too dead, and it basically responds to keyboard and mouse messages. What if the model needs to be rotated around the X, Y or Z axis for ease of manipulation? We thought of Actor's RotateX RotateY and other methods, but when I wrote the code that the camera does not move and the Actor rotates, tragedy happened.

    The built-in interaction style of vtk uses vtkInteractorStyleTrackballCamera to respond to the mouse, which is to operate the camera to achieve interaction. If the Actor rotates around the X axis at this time, and you move the camera to observe the front view, you will find that the front view has also changed. . This is not what we want to see. The problem is that the same window uses 2 interaction methods with different principles. The only way is to unify, either to operate the camera, or to operate the Actor. So how do you operate the camera to rotate around the X axis? The sample code is given below:

vtkTransform* trans = vtkTransform::New();
trans->PostMultiply(); //must use this method, it is easy to misunderstand here
for (int i = 0;; i++)
{
reWin->Render();
double pos[3];
pos[0]= render->GetActiveCamera()->GetPosition()[0];
    pos[1] = render->GetActiveCamera()->GetPosition()[1];
pos[2] = render->GetActiveCamera()->GetPosition()[2];
double viewup[3];
viewup[0]= render->GetActiveCamera()->GetViewUp()[0];
viewup[1] = render->GetActiveCamera ()->GetViewUp()[1];
viewup[2] = render->GetActiveCamera()->GetViewUp()[2];
trans->Identity();
trans->Translate(-cent[0], - cent[1], -cent[2]); //cent is the center point of the model
trans->RotateX(1);
trans->Translate(cent[0], cent[1],cent[2]);
double* viewupnew = trans->TransformDoubleVector(viewup); //Rotate camera up vector
render->GetActiveCamera()->SetViewUp(viewupnew); 
double posnew[3];
trans->TransformPoint(pos, posnew); //with The center point of the model and the X axis are the axes, and the camera position is rotated render->GetActiveCamera()->SetPosition(posnew); render->ResetCamera(); }







trans->Delete();

There is a problem here: render->GetActiveCamera()->GetViewUp() returns a pointer, if you define a pointer to receive this return value: double* vec=render->GetActiveCamera()->GetViewUp() ,double* pos=render->GetActiveCamera()->GetPosition(), there is always an error when running the program. At first I thought it was returning a separate piece of memory. Later, after repeated debugging, I found that after calling the above two statements successively, vec and pos point to the same variable, tragedy! Maybe the pointers returned by vtk all point to the same piece of memory (without going into details), in short, it is best not to use pointers to the pointers returned by vtk. With the basic concept of the above code, rotation around any axis is no problem.

2. Panning problem: What if I want to click on a button to make the model pan without using the mouse? vtk does not give an existing interface. After reading the implementation code of vtkInteractortrackballCamera in detail, I made one according to the pan member function. With this example, we can write our own translation as we like. The code is as follows:

void Pan(vtkRenderer* render,vtkRenderWindow* reWin)
{double viewFocus[4], focalDepth, viewPoint[3];double newPickPoint[4], oldPickPoint[4], motionVector[3];// Calculate the focal depth since we'll be using it a lotvtkCamera *camera = render->GetActiveCamera();camera->GetFocalPoint(viewFocus);render->SetWorldPoint(viewFocus[0], viewFocus[1], viewFocus[2],viewFocus[3]);render->WorldToDisplay();viewFocus[0] = render->GetDisplayPoint()[0];viewFocus[1] = render->GetDisplayPoint()[1];viewFocus[2] = render->GetDisplayPoint()[2];viewFocus[3] = render->GetDisplayPoint()[3];focalDepth = viewFocus[2];double x[2];x[0]= reWin->GetSize()[0];























x[1] = reWin->GetSize()[1];
double x1 = x[0] / 2, y1 = x[1] / 2;


render->SetDisplayPoint(x1, y1, focalDepth);
render->DisplayToWorld();
oldPickPoint[0] = render->GetWorldPoint()[0];
oldPickPoint[1] = render->GetWorldPoint()[1];
oldPickPoint[2] = render->GetWorldPoint()[2];
oldPickPoint[3] = render->GetWorldPoint()[3];
// Has to recalc old mouse point since the viewport has moved,
// so can't move it outside the loop
y1 = y1 + 0.5;


render->SetDisplayPoint(x1, y1, focalDepth);
render->DisplayToWorld();
newPickPoint[0] = render->GetWorldPoint()[0];
newPickPoint[1] = render->GetWorldPoint()[1];
newPickPoint[2] = render->GetWorldPoint()[2];
newPickPoint[3] = render->GetWorldPoint()[3];


// Camera motion is reversed


motionVector[0] = oldPickPoint[0] - newPickPoint[0];
motionVector[1] = oldPickPoint[1] - newPickPoint[1];
motionVector[2] = oldPickPoint[2] - newPickPoint[2];


camera->GetFocalPoint(viewFocus);
camera->GetPosition(viewPoint);
camera->SetFocalPoint(motionVector[0] + viewFocus[0],
motionVector[1] + viewFocus[1],
motionVector[2] + viewFocus[2]);


camera->SetPosition(motionVector[0] + viewPoint[0],
motionVector[1] + viewPoint[1],
motionVector[2] + viewPoint[2]);


reWin->Render();

}

The core of the above code lies in the mutual conversion of device coordinates and world coordinates, which is easy to understand and does not explain much.

3, vtk and MFC joint problem

 The examples given by vtk are to put vtkMFCWindow as a member variable in CView. This is very uncomfortable, and it is not easy to control a message or something. The solution is to build a CVtkView yourself, inherit CView, copy the code to the corresponding message handler of CVtkView against the implementation code of vtkMfcWindow, and then you can write your own CVtkView as you like, and also inherit all the functions of vtkMFC, flexible too much.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324670808&siteId=291194637