这可能更像是一个通用的图形编程问题,但目前这是在 macOS 上使用 Apple 的 Metal 框架的上下文中。
在 NSView mouseDown
中,只需调用以下命令即可轻松获取鼠标按下事件发生位置的本地坐标:
NSPoint localPoint = [self convertPoint:event.locationInWindow fromView:nil];
给定该局部点,需要哪些步骤来确定在渲染场景的上下文中发生鼠标按下的位置?
现在,我只是在 MTKView
中渲染一个 2D 平面。二维平面可以在 z 轴上缩放、平移和旋转。我可以用蛮力解决方案,因为场景非常简单,但我想知道更正确的方法是什么。
感觉好像我必须在我的 Objective-C 代码中复制一些顶点着色器逻辑,以确保正确应用所有变换。但是我不太确定应用旋转时这个世界是如何工作的。
很少有 Metal 教程或引用资料谈论鼠标输入和坐标系如何交互。任何见解将不胜感激。
在此示例中,如果用户单击橙色平面,您如何确定该特定对象内的归一化坐标? (在这个例子中,它可能类似于 [0.8, 0.9])
最佳答案
部分是出于这个问题的提示,我写了 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/