使用触摸板放大一个点(使用 Objective-C 在 opengl 或 metalkit 中缩放和平移和旋转)
Zoom in on a point with touchpad(using scale and translate and rotate in opengl or metalkit with Objective-C)
我只是创建了一个类似于 osx 预览应用的应用。我使用 opengl 或 metalkit 来渲染图像。我可以通过一些矩阵以中心点 (0,0) 进行缩放,但是我不能像预览应用程序那样使用触摸板用两个手指之间的点进行缩放,因为我不知道如何创建我的模型矩阵。
我只是在苹果开发论坛上问我的问题,我在github上找到了演示,但是没有人可以帮助我。
- (void)magnifyWithEvent:(NSEvent *)event {
NSPoint eventLocation = [event locationInWindow];
NSPoint center = [self.view convertPoint:eventLocation fromView:nil];
NSPoint openglCenter = CGPointMake(center.x / ([[[NSApplication sharedApplication] mainWindow] frame].size.width / 2.0) - 1.0, center.y / ([[[NSApplication sharedApplication] mainWindow] frame].size.height / 2.0) - 1.0);
NSRect frame = [[[NSApplication sharedApplication] mainWindow] frame];
if ([event magnification] > 0)
{
if ([self zoomValue] <= 2.0)
{
[self setZoomValue:[self zoomValue] + [event magnification]];
if(self.zoomValue > 2.0) {
return;
}
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
} else {
[self setZoomValue:2.0];
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
}
}
else if ([event magnification] < 0)
{
if ([self zoomValue] + [event magnification] >= 1.0)
{
[self setZoomValue:[self zoomValue] + [event magnification]];
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
}
else
{
[self setZoomValue:1.0];
if(self.zoomValue < 1.0) {
return;
}
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
}
}
}
要围绕任意点进行缩放,您需要:
- 按(中心 - 点)翻译,从而更改步骤 2 的原点
- 按必要的数量缩放
- 平移-(中心-点),从而将原点返回到(0,0)
您完全漏掉了其中一个翻译。你需要这样的东西:
NSPoint eventLocation = [event locationInWindow];
NSPoint center = [self.view convertPoint:eventLocation fromView:nil];
double transX = 1.0 - center.x / (frame.size.width / 2.0);
double transY = 1.0 - center.y / (frame.size.height / 2.0);
GLKMatrix4 trans = GLKMatrix4Translate(GLKMatrix4Identity, transX, transY, 0);
GLKMatrix4 transBack = GLKMatrix4Translate(GLKMatrix4Identity, -transX, -transY, 0);
GLKMatrix4 scaleMatrix = GLKMatrix4Scale(GLKMatrix4Identity, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply( transBack, GLKMatrix4Multiply( GLKMatrix4Multiply( scaleMatrix, trans ), _baseScaleMatrix ) );
编辑:您也不能将投影矩阵 (_baseScaleMatrix) 混合到模型矩阵中,必须先应用投影,然后再应用模型矩阵。
我只是创建了一个类似于 osx 预览应用的应用。我使用 opengl 或 metalkit 来渲染图像。我可以通过一些矩阵以中心点 (0,0) 进行缩放,但是我不能像预览应用程序那样使用触摸板用两个手指之间的点进行缩放,因为我不知道如何创建我的模型矩阵。
我只是在苹果开发论坛上问我的问题,我在github上找到了演示,但是没有人可以帮助我。
- (void)magnifyWithEvent:(NSEvent *)event {
NSPoint eventLocation = [event locationInWindow];
NSPoint center = [self.view convertPoint:eventLocation fromView:nil];
NSPoint openglCenter = CGPointMake(center.x / ([[[NSApplication sharedApplication] mainWindow] frame].size.width / 2.0) - 1.0, center.y / ([[[NSApplication sharedApplication] mainWindow] frame].size.height / 2.0) - 1.0);
NSRect frame = [[[NSApplication sharedApplication] mainWindow] frame];
if ([event magnification] > 0)
{
if ([self zoomValue] <= 2.0)
{
[self setZoomValue:[self zoomValue] + [event magnification]];
if(self.zoomValue > 2.0) {
return;
}
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
} else {
[self setZoomValue:2.0];
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
}
}
else if ([event magnification] < 0)
{
if ([self zoomValue] + [event magnification] >= 1.0)
{
[self setZoomValue:[self zoomValue] + [event magnification]];
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
}
else
{
[self setZoomValue:1.0];
if(self.zoomValue < 1.0) {
return;
}
self.slider.floatValue = [self zoomValue];
self.panMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.swipX / (frame.size.width / 2.0), -self.swipY / (frame.size.height / 2.0), 1);
self.scaleMatrix = GLKMatrix4Scale(self.baseScaleMatrix, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply(self.panMatrix, self.scaleMatrix);
[self.testView makeChangeWithMat:model];
}
}
}
要围绕任意点进行缩放,您需要:
- 按(中心 - 点)翻译,从而更改步骤 2 的原点
- 按必要的数量缩放
- 平移-(中心-点),从而将原点返回到(0,0)
您完全漏掉了其中一个翻译。你需要这样的东西:
NSPoint eventLocation = [event locationInWindow];
NSPoint center = [self.view convertPoint:eventLocation fromView:nil];
double transX = 1.0 - center.x / (frame.size.width / 2.0);
double transY = 1.0 - center.y / (frame.size.height / 2.0);
GLKMatrix4 trans = GLKMatrix4Translate(GLKMatrix4Identity, transX, transY, 0);
GLKMatrix4 transBack = GLKMatrix4Translate(GLKMatrix4Identity, -transX, -transY, 0);
GLKMatrix4 scaleMatrix = GLKMatrix4Scale(GLKMatrix4Identity, self.zoomValue, self.zoomValue, 1);
GLKMatrix4 model = GLKMatrix4Multiply( transBack, GLKMatrix4Multiply( GLKMatrix4Multiply( scaleMatrix, trans ), _baseScaleMatrix ) );
编辑:您也不能将投影矩阵 (_baseScaleMatrix) 混合到模型矩阵中,必须先应用投影,然后再应用模型矩阵。