objective-c - 如何检测 MTKView 中发生鼠标按下事件的位置?

标签 objective-c macos metal metalkit

这可能更像是一个通用的图形编程问题,但目前这是在 macOS 上使用 Apple 的 Metal 框架的上下文中。

NSView mouseDown 中,只需调用以下命令即可轻松获取鼠标按下事件发生位置的本地坐标:

NSPoint localPoint = [self convertPoint:event.locationInWindow fromView:nil];

给定该局部点,需要哪些步骤来确定在渲染场景的上下文中发生鼠标按下的位置?

现在,我只是在 MTKView 中渲染一个 2D 平面。二维平面可以在 z 轴上缩放、平移和旋转。我可以用蛮力解决方案,因为场景非常简单,但我想知道更正确的方法是什么。

感觉好像我必须在我的 Objective-C 代码中复制一些顶点着色器逻辑,以确保正确应用所有变换。但是我不太确定应用旋转时这个世界是如何工作的。

很少有 Metal 教程或引用资料谈论鼠标输入和坐标系如何交互。任何见解将不胜感激。

在此示例中,如果用户单击橙色平面,您如何确定该特定对象内的归一化坐标? (在这个例子中,它可能类似于 [0.8, 0.9])

MTKView Diagram

最佳答案

部分是出于这个问题的提示,我写了 an article关于这个主题,你可能会发现有用。示例代码是用 Swift 编写的,但概念很容易转移。

这是在 macOS 上从屏幕空间坐标转换为世界空间坐标的 Objective-C 算法的草图:

// Get viewport dimensions
CGFloat width = view.bounds.size.width;
CGFloat height = view.bounds.size.height;

// Convert from AppKit view coordinates to Metal viewport coordinates
CGPoint location = [view convertPoint:event.locationInWindow toView:nil];
location.y = height - location.y;

// Compute clip-to-view and view-to-world matrices
simd_float4x4 inverseProjectionMatrix = simd_inverse(projectionMatrix);
simd_float4x4 inverseViewMatrix = simd_inverse(viewMatrix);

// Convert from screen coordinates to clip-space coordinates
float clipX = (2 * location.x) / width - 1;
float clipY = 1 - (2 * location.y) / height;
simd_float4 clipCoords = (simd_float4){ clipX, clipY, 0, 1 };

// Determine direction of picking ray in view space
simd_float4 eyeRayDir = simd_mul(inverseProjectionMatrix, clipCoords);
eyeRayDir.z = -1;
eyeRayDir.w = 0;

// Determine direction of picking ray in world space
simd_float4 worldRayDir = simd_mul(inverseViewMatrix, eyeRayDir);
worldRayDir = simd_normalize(worldRayDir);

// Determine origin of picking ray in world space
simd_float4 eyeRayOrigin = (simd_float4){ 0, 0, 0, 1};
simd_float4 worldRayOrigin = simd_mul(inverseViewMatrix, eyeRayOrigin);

...do intersection testing against object bounds...

关于objective-c - 如何检测 MTKView 中发生鼠标按下事件的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53125024/

相关文章:

ios - 为什么我的 ios/osx 框架忽略 GCC_PREFIX_HEADER?

ios - 我怎样才能用 crittercism 解决 SIGSEGV

ios - iOS 8.0 升级后 UILabel 不显示

iOS:使用 CoreText 更好地说明理由

iphone - UISearchDisplayController 重置 contentInset

Mac 操作系统上的数据库

python - 有没有办法让 python 包 psutil 检测 Debian/Ubuntu 和 OSX 上未安装的设备

ios - Metal 最佳实践 : Triple-buffering – Textures too?

ios - Metal IOS 中的网格

gpgpu - 您可以使用 Apple 的 Metal 进行通用 GPU 编程吗?