Увеличьте точку с помощью сенсорной панели (используя масштабирование, перевод и вращение в opengl или металкит с Objective-C) - PullRequest
0 голосов
/ 18 апреля 2019

Я просто создаю приложение, такое как osx preview app.Я использую opengl или metalkit для рендеринга изображения.Я могу сделать масштабирование с центральной точкой (0,0) по некоторой матрице, но я не могу сделать масштабирование с точкой между двумя пальцами с помощью сенсорной панели, как приложение предварительного просмотра, потому что я не знаю, как создать свою матрицу модели.

Я просто задаю свою проблему на форуме разработки Apple, и я нахожу демо на 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];
        }
    }
}

1 Ответ

0 голосов
/ 18 апреля 2019

Чтобы увеличить вокруг произвольной точки, вам нужно:

  1. Перевести на (центральная точка), тем самым изменив начало координат для шага 2
  2. Шкала на необходимую сумму
  3. Перевести обратно на - (центральная точка), вернув, таким образом, начало координат обратно к (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) в матрице модели, сначала необходимо применить проекцию, а затем матрицу модели.

...