/*========================================================================= Program: Visualization Toolkit Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkVRHMDCamera.h" #include "vtkMatrix3x3.h" #include "vtkMatrix4x4.h" #include "vtkOpenGLError.h" #include "vtkOpenGLState.h" #include "vtkRenderer.h" #include "vtkTransform.h" #include "vtkVRRenderWindow.h" #include //------------------------------------------------------------------------------ vtkVRHMDCamera::vtkVRHMDCamera() { // approximate for Vive // we use the projection matrix directly from the vive // so this is just to help make view <--> display // adjustments reasonable, not correct, just reasonable this->SetViewAngle(110.0); } vtkVRHMDCamera::~vtkVRHMDCamera() = default; // a reminder, with vtk order matrices multiplcation goes right to left // e.g. vtkMatrix4x4::Multiply(BtoC, AtoB, AtoC); //------------------------------------------------------------------------------ void vtkVRHMDCamera::Render(vtkRenderer* ren) { vtkOpenGLClearErrorMacro(); vtkVRRenderWindow* win = vtkVRRenderWindow::SafeDownCast(ren->GetRenderWindow()); vtkOpenGLState* ostate = win->GetState(); int renSize[2]; win->GetRenderBufferSize(renSize[0], renSize[1]); // if were on a stereo renderer draw to special parts of screen if (win->GetMultiSamples() && !ren->GetSelector()) { ostate->vtkglEnable(GL_MULTISAMPLE); } ostate->vtkglViewport(0, 0, renSize[0], renSize[1]); ostate->vtkglScissor(0, 0, renSize[0], renSize[1]); if ((ren->GetRenderWindow())->GetErase() && ren->GetErase()) { ren->Clear(); } vtkOpenGLCheckErrorMacro("failed after Render"); } //------------------------------------------------------------------------------ void vtkVRHMDCamera::GetKeyMatrices(vtkRenderer* ren, vtkMatrix4x4*& wcvc, vtkMatrix3x3*& normMat, vtkMatrix4x4*& vcdc, vtkMatrix4x4*& wcdc) { if (ren->GetSelector()) { return this->Superclass::GetKeyMatrices(ren, wcvc, normMat, vcdc, wcdc); } // has the camera changed? if (ren != this->LastRenderer || this->MTime > this->KeyMatrixTime || ren->GetMTime() > this->KeyMatrixTime) { vtkVRRenderWindow* win = vtkVRRenderWindow::SafeDownCast(ren->GetRenderWindow()); // on left eye render we compute the NormalMatrix, this should be fairly // accurate for both eyes. if (this->LeftEye) { this->UpdateWorldToEyeMatrices(ren); this->UpdateEyeToProjectionMatrices(ren); vtkMatrix4x4* w2v = this->GetModelViewTransformMatrix(); this->WCVCMatrix->DeepCopy(w2v); // only compute normal matrix once for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { this->NormalMatrix->SetElement(i, j, w2v->GetElement(i, j)); } } this->NormalMatrix->Invert(); } if (this->LeftEye) { this->SetCameraFromWorldToDeviceMatrix(this->WorldToLeftEyeMatrix, win->GetPhysicalScale()); this->ModelViewTransform->SetMatrix(this->WorldToLeftEyeMatrix); this->WCVCMatrix->DeepCopy(this->WorldToLeftEyeMatrix); this->WCVCMatrix->Transpose(); vtkMatrix4x4::Multiply4x4( this->LeftEyeToProjectionMatrix, this->WorldToLeftEyeMatrix, this->WCDCMatrix); this->WCDCMatrix->Transpose(); vtkMatrix4x4::Multiply4x4(this->LeftEyeToProjectionMatrix, this->PhysicalToLeftEyeMatrix, this->PhysicalToProjectionMatrixForLeftEye); } else { this->SetCameraFromWorldToDeviceMatrix(this->WorldToRightEyeMatrix, win->GetPhysicalScale()); this->ModelViewTransform->SetMatrix(this->WorldToRightEyeMatrix); this->WCVCMatrix->DeepCopy(this->WorldToRightEyeMatrix); this->WCVCMatrix->Transpose(); vtkMatrix4x4::Multiply4x4( this->RightEyeToProjectionMatrix, this->WorldToRightEyeMatrix, this->WCDCMatrix); this->WCDCMatrix->Transpose(); vtkMatrix4x4::Multiply4x4(this->RightEyeToProjectionMatrix, this->PhysicalToRightEyeMatrix, this->PhysicalToProjectionMatrixForRightEye); } this->KeyMatrixTime.Modified(); this->LastRenderer = ren; } wcdc = this->WCDCMatrix; wcvc = this->WCVCMatrix; normMat = this->NormalMatrix; if (this->LeftEye) { vcdc = this->LeftEyeToProjectionMatrix; } else { vcdc = this->RightEyeToProjectionMatrix; } } //------------------------------------------------------------------------------ void vtkVRHMDCamera::GetPhysicalToProjectionMatrix(vtkMatrix4x4*& physToProjectionMat) { if (this->LeftEye) { physToProjectionMat = this->PhysicalToProjectionMatrixForLeftEye; } else { physToProjectionMat = this->PhysicalToProjectionMatrixForRightEye; } } //------------------------------------------------------------------------------ void vtkVRHMDCamera::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "PhysicalToLeftEyeMatrix: "; this->PhysicalToLeftEyeMatrix->PrintSelf(os, indent); os << indent << "PhysicalToRightEyeMatrix: "; this->PhysicalToRightEyeMatrix->PrintSelf(os, indent); os << indent << "WorldToLeftEyeMatrix: "; this->WorldToLeftEyeMatrix->PrintSelf(os, indent); os << indent << "WorldToRightEyeMatrix: "; this->WorldToRightEyeMatrix->PrintSelf(os, indent); os << indent << "LeftEyeToProjectionMatrix: "; this->LeftEyeToProjectionMatrix->PrintSelf(os, indent); os << indent << "RightEyeToProjectionMatrix: "; this->RightEyeToProjectionMatrix->PrintSelf(os, indent); os << indent << "PhysicalToProjectionMatrixForLeftEye: "; this->PhysicalToProjectionMatrixForLeftEye->PrintSelf(os, indent); os << indent << "PhysicalToProjectionMatrixForRightEye: "; this->PhysicalToProjectionMatrixForRightEye->PrintSelf(os, indent); }