// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkZSpaceCoreCompatibilitySDKManager.h" #include "vtkBoundingBox.h" #include "vtkMatrix4x4.h" #include "vtkObjectFactory.h" #include "vtkRenderWindow.h" #include "vtkSmartPointer.h" #include "vtkStringFormatter.h" #include "vtkTransform.h" #include "vtkVector.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkZSpaceCoreCompatibilitySDKManager); // Macros used to check if initialisation has been done before // using function entry points. #define ZSPACE_RETURN_IF_NOT_INIT() \ if (!this->Initialized) \ { \ vtkErrorMacro("zSpace manager not initialized."); \ return; \ } #define ZSPACE_RETURN_VAL_IF_NOT_INIT(value) \ if (!this->Initialized) \ { \ vtkErrorMacro("zSpace manager not initialized."); \ return value; \ } #define ZSPACE_CHECK_ERROR(fn, error) \ if (error != ZC_COMPAT_ERROR_OK) \ { \ std::string errorMessage = std::string("zSpace Core Compatibility API call \"") + \ std::string(#fn) + \ "\" failed with error " \ "code " + \ vtk::to_string(static_cast(error)) + "."; \ vtkErrorMacro(<< "vtkZSpaceCoreCompatibilitySDKManager::" << #fn << " error : " << error); \ } static const char* ZSPACE_CORE_COMPATIBILITY_DLL_FILE_PATH = "zSpaceCoreCompatibility" #ifdef _WIN64 "64" #else "32" #endif ; //------------------------------------------------------------------------------ vtkZSpaceCoreCompatibilitySDKManager::vtkZSpaceCoreCompatibilitySDKManager() = default; //------------------------------------------------------------------------------ vtkZSpaceCoreCompatibilitySDKManager::~vtkZSpaceCoreCompatibilitySDKManager() = default; //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::ShutDown() { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error; error = this->EntryPts.zccompatShutDown(this->ZSpaceContext); ZSPACE_CHECK_ERROR(zccompatShutDown, error); this->Initialized = false; } //------------------------------------------------------------------------------ bool vtkZSpaceCoreCompatibilitySDKManager::loadZspaceCoreCompatibilityEntryPoints( const char* zSpaceCoreCompatDllFilePath, HMODULE& dllModuleHandle, zSpaceCoreCompatEntryPoints& entryPoints) { dllModuleHandle = LoadLibraryA(zSpaceCoreCompatDllFilePath); if (dllModuleHandle == nullptr) { // If the release variant of the zSpace Core Compatibility API DLL // could not be loaded, attempt to the debug variant instead. std::string zSpaceCoreCompatDllDebugFilePath(zSpaceCoreCompatDllFilePath); zSpaceCoreCompatDllDebugFilePath.append("_D"); dllModuleHandle = LoadLibraryA(zSpaceCoreCompatDllDebugFilePath.c_str()); if (dllModuleHandle == nullptr) { vtkErrorMacro(<< "Win32 Error : " << "Failed to load zSpace Core Compatibility API DLL."); return false; } } #define ZC_COMPAT_SAMPLE_LOCAL_LOAD_ENTRY_POINT(undecoratedFuncName) \ { \ void* entryPointProcAddress = \ GetProcAddress(dllModuleHandle, "zccompat" #undecoratedFuncName); \ \ if (entryPointProcAddress == nullptr) \ { \ vtkErrorMacro(<< "Win32 Error : " \ << "Failed to get zSpace Core Compatibility entry point " \ << "proc address for entry point " \ << "\"zccompat" << #undecoratedFuncName << "\"."); \ \ return false; \ } \ \ entryPoints.zccompat##undecoratedFuncName = \ reinterpret_cast(entryPointProcAddress); \ } ZC_COMPAT_REFLECTION_LIST_UNDECORATED_FUNC_NAMES(ZC_COMPAT_SAMPLE_LOCAL_LOAD_ENTRY_POINT) #undef ZC_COMPAT_SAMPLE_LOCAL_LOAD_ENTRY_POINT return true; } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::InitializeZSpace() { const bool didSucceed = loadZspaceCoreCompatibilityEntryPoints( ZSPACE_CORE_COMPATIBILITY_DLL_FILE_PATH, this->zSpaceCoreCompatDllModuleHandle, this->EntryPts); if (!didSucceed) { vtkErrorMacro("Unable to load the SDK functions entry points."); return; } this->Initialized = true; ZCCompatError error; // Initialize the zSpace SDK. This MUST be called before // calling any other zSpace API. error = this->EntryPts.zccompatInitialize(nullptr, nullptr, &this->ZSpaceContext); ZSPACE_CHECK_ERROR(zccompatInitialize, error); // Check the SDK version ZSInt32 major, minor, patch; error = this->EntryPts.zccompatGetRuntimeVersion(this->ZSpaceContext, &major, &minor, &patch); ZSPACE_CHECK_ERROR(zccompatGetRuntimeVersion, error); vtkDebugMacro(<< "zSpace SDK version: " << major << "." << minor << "." << patch); int numDisplays; error = this->EntryPts.zccompatGetNumDisplays(this->ZSpaceContext, &numDisplays); this->Displays.clear(); this->Displays.reserve(numDisplays); for (int i = 0; i < numDisplays; i++) { ZCCompatDisplay displayHandle; error = this->EntryPts.zccompatGetDisplayByIndex(this->ZSpaceContext, i, &displayHandle); ZSPACE_CHECK_ERROR(zccompatGetDisplayByIndex, error); ZCCompatDisplayType displayType; error = this->EntryPts.zccompatGetDisplayType(displayHandle, &displayType); ZSPACE_CHECK_ERROR(zccompatGetDisplayType, error); switch (displayType) { case ZC_COMPAT_DISPLAY_TYPE_GENERIC: this->Displays.push_back("Generic"); break; case ZC_COMPAT_DISPLAY_TYPE_ZSPACE: this->Displays.push_back("ZSpace"); break; default: this->Displays.push_back("Unknown"); break; } } // Retrieve the zSpace primary viewport object and grab its associated frustum. // Note: The zSpace viewport is abstract and not an actual window/viewport // that is created and registered through the Windows OS. It manages // a zSpace stereo frustum, which is responsible for various stereoscopic // 3D calculations such as calculating the view and projection matrices for // each eye. if (this->ViewportHandle != nullptr) { this->EntryPts.zccompatDestroyViewport(this->ViewportHandle); this->ViewportHandle = nullptr; } error = this->EntryPts.zccompatGetPrimaryViewport(this->ZSpaceContext, &this->ViewportHandle); ZSPACE_CHECK_ERROR(zccompatCreateViewport, error); error = this->EntryPts.zccompatGetFrustum(this->ViewportHandle, &this->FrustumHandle); ZSPACE_CHECK_ERROR(zccompatGetFrustum, error); // Enable auto stereo. error = this->EntryPts.zccompatSetFrustumAttributeB( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_AUTO_STEREO_ENABLED, true); ZSPACE_CHECK_ERROR(zccompatSetFrustumAttributeB, error); error = this->EntryPts.zccompatSetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_IPD, this->InterPupillaryDistance); ZSPACE_CHECK_ERROR(zccompatSetFrustumAttributeF32, error); error = this->EntryPts.zccompatSetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_HEAD_SCALE, 1.f); ZSPACE_CHECK_ERROR(zccompatSetFrustumAttributeF32, error); // Disable the portal mode error = this->EntryPts.zccompatSetFrustumPortalMode(this->FrustumHandle, 0); ZSPACE_CHECK_ERROR(zccompatSetFrustumPortalMode, error); error = this->EntryPts.zccompatGetNumTargetsByType( this->ZSpaceContext, ZC_COMPAT_TARGET_TYPE_PRIMARY, &this->StylusTargets); ZSPACE_CHECK_ERROR(zccompatGetNumTargetsByType, error); error = this->EntryPts.zccompatGetNumTargetsByType( this->ZSpaceContext, ZC_COMPAT_TARGET_TYPE_HEAD, &this->HeadTargets); ZSPACE_CHECK_ERROR(zccompatGetNumTargetsByType, error); error = this->EntryPts.zccompatGetNumTargetsByType( this->ZSpaceContext, ZC_COMPAT_TARGET_TYPE_SECONDARY, &this->SecondaryTargets); ZSPACE_CHECK_ERROR(zccompatGetNumTargetsByType, error); // Grab a handle to the stylus target. error = this->EntryPts.zccompatGetTargetByType( this->ZSpaceContext, ZC_COMPAT_TARGET_TYPE_PRIMARY, 0, &this->StylusHandle); ZSPACE_CHECK_ERROR(zccompatGetTargetByType, error); // Find the zSpace display and set the window position // to be the top left corner of the zSpace display. error = this->EntryPts.zccompatGetDisplayByType( this->ZSpaceContext, ZC_COMPAT_DISPLAY_TYPE_ZSPACE, 0, &this->DisplayHandle); ZSPACE_CHECK_ERROR(zccompatGetDisplayByType, error); error = this->EntryPts.zccompatGetDisplayPosition(this->DisplayHandle, &this->WindowX, &this->WindowY); ZSPACE_CHECK_ERROR(zccompatGetDisplayPosition, error); error = this->EntryPts.zccompatGetDisplayNativeResolution( this->DisplayHandle, &this->WindowWidth, &this->WindowHeight); ZSPACE_CHECK_ERROR(zccompatGetDisplayNativeResolution, error); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::UpdateViewport() { ZSPACE_RETURN_IF_NOT_INIT(); if (!this->RenderWindow) { vtkErrorMacro("No render window has been set to the zSpace SDK manager !"); return; } int* position = this->RenderWindow->GetPosition(); int* size = this->RenderWindow->GetSize(); ZCCompatError error; error = this->EntryPts.zccompatSetViewportPosition(this->ViewportHandle, position[0], position[1]); ZSPACE_CHECK_ERROR(zccompatSetViewportPosition, error); error = this->EntryPts.zccompatSetViewportSize(this->ViewportHandle, size[0], size[1]); ZSPACE_CHECK_ERROR(zccompatSetViewportSize, error); // Update inter pupillary distance error = this->EntryPts.zccompatSetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_IPD, this->InterPupillaryDistance); ZSPACE_CHECK_ERROR(zccompatSetFrustumAttributeF32, error); // Near and far plane error = this->EntryPts.zccompatSetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_NEAR_CLIP, this->NearPlane); ZSPACE_CHECK_ERROR(zccompatSetFrustumAttributeF32, error); error = this->EntryPts.zccompatSetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_FAR_CLIP, this->FarPlane); ZSPACE_CHECK_ERROR(zccompatSetFrustumAttributeF32, error); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::UpdateTrackers() { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error; // Update the zSpace SDK. This updates both tracking information // as well as the head poses for any frustums that have been created. error = this->EntryPts.zccompatUpdate(this->ZSpaceContext); ZSPACE_CHECK_ERROR(zccompatUpdate, error); // Update the stylus matrix ZCCompatTrackerPose stylusPose; error = this->EntryPts.zccompatGetTargetPose(this->StylusHandle, &stylusPose); ZSPACE_CHECK_ERROR(zccompatGetTargetPose, error); error = this->EntryPts.zccompatTransformMatrix(this->ViewportHandle, ZC_COMPAT_COORDINATE_SPACE_TRACKER, ZC_COMPAT_COORDINATE_SPACE_CAMERA, &stylusPose.matrix); // Manual transfo added ZSPACE_CHECK_ERROR(zccompatTransformMatrix, error); this->ConvertZSpaceMatrixToVTKMatrix(stylusPose.matrix, this->StylusMatrixColMajor); // The stylus direction is the normalized negative Z axis of the pose this->StylusMatrixColMajor->SetElement(2, 0, -this->StylusMatrixColMajor->GetElement(2, 0)); this->StylusMatrixColMajor->SetElement(2, 1, -this->StylusMatrixColMajor->GetElement(2, 1)); this->StylusMatrixColMajor->SetElement(2, 2, -this->StylusMatrixColMajor->GetElement(2, 2)); vtkNew invView; vtkMatrix4x4::Invert(this->CenterEyeViewMatrix.GetPointer(), invView); // Convert from camera space to world space vtkMatrix4x4::Multiply4x4(invView, this->StylusMatrixColMajor, this->StylusMatrixColMajor); // Transpose the matrix to be used by VTK vtkMatrix4x4::Transpose(this->StylusMatrixColMajor, this->StylusMatrixRowMajor); this->StylusTransformRowMajor->SetMatrix(this->StylusMatrixRowMajor); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::UpdateViewAndProjectionMatrix() { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error; // Update the view matrix for each eye ZSMatrix4 zccompatViewMatrix; error = this->EntryPts.zccompatGetFrustumViewMatrix( this->FrustumHandle, ZC_COMPAT_EYE_CENTER, &zccompatViewMatrix); ZSPACE_CHECK_ERROR(zccompatGetFrustumViewMatrix, error); this->ConvertAndTransposeZSpaceMatrixToVTKMatrix(zccompatViewMatrix, this->CenterEyeViewMatrix); error = this->EntryPts.zccompatGetFrustumViewMatrix( this->FrustumHandle, ZC_COMPAT_EYE_LEFT, &zccompatViewMatrix); ZSPACE_CHECK_ERROR(zccompatGetFrustumViewMatrix, error); this->ConvertAndTransposeZSpaceMatrixToVTKMatrix(zccompatViewMatrix, this->LeftEyeViewMatrix); error = this->EntryPts.zccompatGetFrustumViewMatrix( this->FrustumHandle, ZC_COMPAT_EYE_RIGHT, &zccompatViewMatrix); ZSPACE_CHECK_ERROR(zccompatGetFrustumViewMatrix, error); this->ConvertAndTransposeZSpaceMatrixToVTKMatrix(zccompatViewMatrix, this->RightEyeViewMatrix); // Update the projection matrix for each eye ZSMatrix4 zccompatProjectionMatrix; error = this->EntryPts.zccompatGetFrustumProjectionMatrix( this->FrustumHandle, ZC_COMPAT_EYE_CENTER, &zccompatProjectionMatrix); ZSPACE_CHECK_ERROR(zccompatGetFrustumProjectionMatrix, error); this->ConvertAndTransposeZSpaceMatrixToVTKMatrix( zccompatProjectionMatrix, this->CenterEyeProjectionMatrix); error = this->EntryPts.zccompatGetFrustumProjectionMatrix( this->FrustumHandle, ZC_COMPAT_EYE_LEFT, &zccompatProjectionMatrix); ZSPACE_CHECK_ERROR(zccompatGetFrustumProjectionMatrix, error); this->ConvertAndTransposeZSpaceMatrixToVTKMatrix( zccompatProjectionMatrix, this->LeftEyeProjectionMatrix); error = this->EntryPts.zccompatGetFrustumProjectionMatrix( this->FrustumHandle, ZC_COMPAT_EYE_RIGHT, &zccompatProjectionMatrix); ZSPACE_CHECK_ERROR(zccompatGetFrustumProjectionMatrix, error); this->ConvertAndTransposeZSpaceMatrixToVTKMatrix( zccompatProjectionMatrix, this->RightEyeProjectionMatrix); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::UpdateButtonState() { ZSPACE_RETURN_IF_NOT_INIT(); ZSBool isButtonPressed; for (int buttonId = vtkZSpaceSDKManager::MiddleButton; buttonId < vtkZSpaceSDKManager::NumberOfButtons; ++buttonId) { this->EntryPts.zccompatIsTargetButtonPressed(this->StylusHandle, buttonId, &isButtonPressed); ButtonState& buttonState = *this->ButtonsState[buttonId]; buttonState = isButtonPressed ? buttonState != vtkZSpaceSDKManager::Pressed ? vtkZSpaceSDKManager::Down : vtkZSpaceSDKManager::Pressed : buttonState != vtkZSpaceSDKManager::None ? vtkZSpaceSDKManager::Up : vtkZSpaceSDKManager::None; } } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::CalculateFrustumFit( const double bounds[6], double position[3], double viewUp[3]) { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error; vtkBoundingBox bBox; bBox.SetBounds(bounds); // Expand the bounding box a little bit to make sure the object is not clipped bBox.Scale(1.5, 1.5, 1.5); // Retrieve viewport size (pixels) ZSInt32 viewportResWidth = 0; ZSInt32 viewportResHeight = 0; error = this->EntryPts.zccompatGetViewportSize( this->ViewportHandle, &viewportResWidth, &viewportResHeight); ZSPACE_CHECK_ERROR(zccompatGetViewportSize, error); // Retrieve display size (meters) ZSFloat displayWidth = 0.0f; ZSFloat displayHeight = 0.0f; error = this->EntryPts.zccompatGetDisplaySize(this->DisplayHandle, &displayWidth, &displayHeight); ZSPACE_CHECK_ERROR(zccompatGetDisplaySize, error); // Retrieve display resolution ZSInt32 displayResWidth = 0; ZSInt32 displayResHeight = 0; error = this->EntryPts.zccompatGetDisplayNativeResolution( this->DisplayHandle, &displayResWidth, &displayResHeight); // Retrieve coupled zone maximum depth value for positive parallax ZSFloat ppMaxDepth = 0.0f; error = this->EntryPts.zccompatGetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_UC_DEPTH, &ppMaxDepth); ZSPACE_CHECK_ERROR(zccompatGetFrustumAttributeF32, error); // Retrieve coupled zone maximum depth value for negative parallax ZSFloat npMaxDepth = 0.0f; error = this->EntryPts.zccompatGetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_CC_DEPTH, &npMaxDepth); ZSPACE_CHECK_ERROR(zccompatGetFrustumAttributeF32, error); // Compute viewport size in meters float viewportWidth = (static_cast(viewportResWidth) / displayResWidth) * displayWidth; float viewportHeight = (static_cast(viewportResHeight) / displayResHeight) * displayHeight; double length[3] = { 0, 0, 0 }; bBox.GetLengths(length); // Compute viewer scale as the maximum of widthScale, heightScale, and depthScale. double widthScale = length[0] / viewportWidth; double heightScale = length[1] / viewportHeight; double depthScale = length[2] / (npMaxDepth - ppMaxDepth); this->ViewerScale = std::max({ depthScale, widthScale, heightScale }); // Get frustum's camera offset (distance to world center) ZSVector3 zsCameraOffset = { 0.0, 0.0, 0.0 }; error = this->EntryPts.zccompatGetFrustumCameraOffset(this->FrustumHandle, &zsCameraOffset); ZSPACE_CHECK_ERROR(zccompatGetFrustumCameraOffset, error); // Compute new frustum's camera viewUp and position double center[3] = { 0.0, 0.0, 0.0 }; bBox.GetCenter(center); vtkVector3d worldCenter = { center[0], center[1], center[2] }; vtkVector3d cameraOffset = { zsCameraOffset.x, zsCameraOffset.y, zsCameraOffset.z }; vtkVector3d cameraForward = (-cameraOffset).Normalized(); vtkVector3d cameraRight = { 1.0f, 0.0f, 0.0f }; vtkVector3d cameraUp = cameraRight.Cross(cameraForward); vtkVector3d cameraPosition = worldCenter - (cameraForward * cameraOffset.Norm() * this->ViewerScale); viewUp[0] = cameraUp.GetX(); viewUp[1] = cameraUp.GetY(); viewUp[2] = cameraUp.GetZ(); position[0] = cameraPosition.GetX(); position[1] = cameraPosition.GetY(); position[2] = cameraPosition.GetZ(); // Set the frustum's viewer scale with the value that was calculated. error = this->EntryPts.zccompatSetFrustumAttributeF32( this->FrustumHandle, ZC_COMPAT_FRUSTUM_ATTRIBUTE_VIEWER_SCALE, this->ViewerScale); ZSPACE_CHECK_ERROR(zccompatSetFrustumAttributeF32, error); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::BeginFrame() { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error = this->EntryPts.zccompatBeginFrame(this->ZSpaceContext); ZSPACE_CHECK_ERROR(zccompatBeginFrame, error); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::EndFrame() { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error = this->EntryPts.zccompatEndFrame(this->ZSpaceContext); ZSPACE_CHECK_ERROR(zccompatEndFrame, error); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::EnableGraphicsBinding() { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error = this->EntryPts.zccompatEnableGraphicsBindingOpenGL(this->ZSpaceContext); ZSPACE_CHECK_ERROR(zccompatEnableGraphicsBindingOpenGL, error); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::SubmitFrame( unsigned int leftText, unsigned int rightText) { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error = this->EntryPts.zccompatSubmitFrameOpenGL(this->ZSpaceContext, leftText, rightText, false); ZSPACE_CHECK_ERROR(zccompatSubmitFrameOpenGL, error); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::GetPerEyeImageResolution( signed int* width, signed int* height) { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error = this->EntryPts.zccompatGetPerEyeImageResolution(this->ZSpaceContext, width, height); ZSPACE_CHECK_ERROR(zccompatGetPerEyeImageResolution, error); } //------------------------------------------------------------------------------ vtkZSpaceSDKManager::StereoDisplayMode vtkZSpaceCoreCompatibilitySDKManager::GetStereoDisplayMode() { ZSPACE_RETURN_VAL_IF_NOT_INIT(QUAD_BUFFER_STEREO); ZCCompatStereoDisplayMode mode = ZC_COMPAT_STEREO_DISPLAY_MODE_QUAD_BUFFER_STEREO; ZCCompatError error = this->EntryPts.zccompatGetStereoDisplayMode(this->ZSpaceContext, &mode); ZSPACE_CHECK_ERROR(zccompatGetStereoDisplayMode, error); return static_cast(mode); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::SetStereoDisplayEnabled(bool enabled) { ZSPACE_RETURN_IF_NOT_INIT(); ZCCompatError error = this->EntryPts.zccompatSetStereoDisplayEnabled(this->ZSpaceContext, enabled); ZSPACE_CHECK_ERROR(zccompatSetStereoDisplayEnabled, error); } //------------------------------------------------------------------------------ bool vtkZSpaceCoreCompatibilitySDKManager::GetStereoDisplayEnabled() { ZSPACE_RETURN_VAL_IF_NOT_INIT(false); ZSBool stereoDisplayEnabled = false; ZCCompatError error = this->EntryPts.zccompatIsStereoDisplayEnabled(this->ZSpaceContext, &stereoDisplayEnabled); ZSPACE_CHECK_ERROR(zccompatSetStereoDisplayEnabled, error); return stereoDisplayEnabled; } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::SetRenderWindow(vtkRenderWindow* renderWindow) { ZSPACE_RETURN_IF_NOT_INIT(); // Give the application window handle to the zSpace Core Compatibility API. HWND hWnd = static_cast(renderWindow->GetGenericWindowId()); ZCCompatError error = this->EntryPts.zccompatSetApplicationWindowHandle(this->ZSpaceContext, hWnd); ZSPACE_CHECK_ERROR(zccompatSetApplicationWindowHandle, error); this->Superclass::SetRenderWindow(renderWindow); } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::ConvertAndTransposeZSpaceMatrixToVTKMatrix( ZSMatrix4 zSpaceMatrix, vtkMatrix4x4* vtkMatrix) { for (int i = 0; i < 16; ++i) { vtkMatrix->SetElement(i % 4, i / 4, zSpaceMatrix.f[i]); } } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::ConvertZSpaceMatrixToVTKMatrix( ZSMatrix4 zSpaceMatrix, vtkMatrix4x4* vtkMatrix) { for (int i = 0; i < 16; ++i) { vtkMatrix->SetElement(i / 4, i % 4, zSpaceMatrix.f[i]); } } //------------------------------------------------------------------------------ void vtkZSpaceCoreCompatibilitySDKManager::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } VTK_ABI_NAMESPACE_END