核心思路就是
1:转NDC
2:乘以PV逆矩阵
3:最大的问题就是解决如何求得Z坐标(屏幕坐标转世界坐标)
void ScreentPosToWorldPos(int selectX, int selectY,double tempWorld[3],vtkRenderer*renderer, vtkRenderWindow*renderWindows)
{
vtkSmartPointer<vtkMatrix4x4> projectionMatrix = renderer->GetActiveCamera()->GetProjectionTransformMatrix(renderer->GetTiledAspectRatio(), 0, 1);
vtkSmartPointer<vtkMatrix4x4> viewMatrix = renderer->GetActiveCamera()->GetViewTransformMatrix();
int* size = renderWindows->GetSize();
double* viewPort = renderer->GetViewport();
double xmin = viewPort[0], ymin = viewPort[1], xmax = viewPort[2], ymax = viewPort[3];//viewPort 已经变成0-1
int width = size[0];
int height = size[1];
double ndcX = 2.0f * (selectX - width * xmin) / (width * (xmax - xmin)) - 1.0f;
double ndcY = 2.0 * (selectY - height * ymin) / (height * (ymax - ymin)) - 1.0;
double z = GetZ(selectX, selectY);//自己去解决,不公开
double ndcZ = 2.0 * z - 1.0;
double eyeCoords[4] = { ndcX, ndcY, ndcZ, 1.0 };
vtkSmartPointer<vtkMatrix4x4> resultMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix4x4::Multiply4x4(projectionMatrix, viewMatrix, resultMatrix);
vtkSmartPointer<vtkMatrix4x4> inverseVP = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix4x4::Invert(resultMatrix, inverseVP);
double world[4] = { 0 };
inverseVP->MultiplyPoint(eyeCoords, world);
for (int index = 0; index < 3; ++index) {
tempWorld[index] = world[index] / world[3];
}
}
void WorldPosToScreentPos(double world[3],int &selectX, int &selectY, vtkRenderer* renderer, vtkRenderWindow* renderWindows)
{
vtkSmartPointer<vtkMatrix4x4> projectionMatrix = renderer->GetActiveCamera()->GetProjectionTransformMatrix(renderer->GetTiledAspectRatio(), 0, 1);
vtkSmartPointer<vtkMatrix4x4> viewMatrix = renderer->GetActiveCamera()->GetViewTransformMatrix();
vtkSmartPointer<vtkMatrix4x4> resultMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix4x4::Multiply4x4(projectionMatrix,viewMatrix,resultMatrix);
double tempPos[4]={0};
tempPos[0]= world[0];
tempPos[1] = world[1];
tempPos[2] = world[2];
tempPos[3] =1.0;
resultMatrix->MultiplyPoint(tempPos, tempPos);
//ndc 坐标
for (int index = 0; index < 3; ++index) {
tempPos[index] = tempPos[index] / tempPos[3];
}
int* size = renderWindows->GetSize();
double* viewPort = renderer->GetViewport();
double xmin = viewPort[0], ymin = viewPort[1], xmax = viewPort[2], ymax = viewPort[3];//viewPort 已经变成0-1
int width = size[0];
int height = size[1];
double ndcX = tempPos[0];
double ndcY = tempPos[1];
selectX = ((ndcX + 1.0)*((width * (xmax - xmin)))+2.0f * (width * xmin))/2.0 ;
selectY = ((ndcY +1.0)* (height * (ymax - ymin))+ 2.0 * (height * ymin))/2.0;
}
以下是结果: