三维屏幕坐标转世界坐标

核心思路就是

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;
}

以下是结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹平华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值