Как преобразовать позицию SCNVector3 в координату CGPoint SCNView?
У меня есть это приложение, которое просто работает в ландшафте.
У меня есть объект на сцене. Этот объект находится в определенной позиции, указанной:
SCNNode * buttonRef = [scene.rootNode childNodeWithName:@"buttonRef" recursively:YES];
SCNVector3 buttonRefPosition = [buttonRef position];
Теперь мне нужно преобразовать это SCNVector3
в mainView
2D координаты, где
mainView = (SCNView *)self.view;
Сцена использует ортогональную камеру, поэтому нет перспективы. Камера является камерой по умолчанию. Нет вращения, нет перевода. Ортогональная шкала камеры составляет 5,4.
Как мне это преобразовать?
Я нашел другие ответы на SO об обратном вопросе, который является преобразованием из CGPoint в SCNVector3, но мне не кажется очевидным, как сделать обратное, из SCNVector3 в CGPoint.
Если SCNView является подклассом UIView, то (0,0) является верхней левой точкой, а в случае ландшафта iPhone 6 (667, 375) является нижней правой точкой.
Эта моя кнопка почти на полной высоте справа и в середине высоты. С точки зрения UIKit я бы сказал, что эта кнопка находится в (600, 187), но когда я делаю это:
SCNNode * buttonRef = [scene.rootNode childNodeWithName:@"buttonRef" recursively:YES];
SCNVector3 buttonRefPosition = [buttonRef position];
SCNVector3 projectedPoint = [mainView projectPoint: buttonRefPosition];
Я получаю ProjectPoint равным (7,8, 375, 0) (?)
и когда я добавляю 10x10 вид к координате (7.8, 375), используя UIKit, я получаю вид внизу слева!!
Как я уже говорил, приложение работает только в альбомной ориентации, но все эти системы координат перепутаны.
2 ответа
Преобразование точек пространства модели в точки пространства экрана называется проецированием (поскольку оно применяет преобразование проекции камеры для отображения из трехмерного пространства в двумерное). Рендерер (через графический процессор) делает это много, много раз за кадр, чтобы получить точки вашей сцены на экране.
Есть также удобный метод, когда вам нужно сделать это самостоятельно: projectPoint:
Довольно старый вопрос, но, к сожалению, ответ @ricksters мне не очень помог, так как projectPoint: продолжает доставлять испорченные координаты вида и в моём случае (та же проблема, что описана @SpaceDog)!
Однако я обнаружил, что в моем случае проблема заключалась в том, что я применил преобразование к своему корневому узлу (перевернул мир вверх ногами;-)). Это явно приводит к неверным результатам из ProjectPoint:...
Поскольку я не мог удалить преобразование, мне пришлось настроить свой ввод для projectPoint: соответственно.
SCNVector3 viewStartPosition = ...; // Some place in the scene
SCNVector3 viewStartPositionRel = SCNVector3FromSCNVector4(SCNMatrix4MultV(self.scene.rootNode.worldTransform, SCNVector4FromSCNVector3(viewStartPosition)));
// Vector from UISceneView 0/0 top/left to start point
SCNVector3 viewStartPositionInViewCoords = [self.sceneView projectPoint:viewStartPositionRel];
К сожалению, Apple не поставляет матричную математику для матриц SCNMatrix4, поэтому используемые (действительно простые) методы обработки матриц также являются "домашними":
/*
SCNVector4FromSCNVector3
*/
SCNVector4 SCNVector4FromSCNVector3(SCNVector3 pV) {
return SCNVector4Make(pV.x, pV.y, pV.z, 0.0);
}
/*
SCNVector3FromSCNVector4
*/
SCNVector3 SCNVector3FromSCNVector4(SCNVector4 pV) {
return SCNVector3Make(pV.x, pV.y, pV.z);
}
/*
SCNMatrix4MultV
*/
SCNVector4 SCNMatrix4MultV(SCNMatrix4 pM, SCNVector4 pV) {
SCNVector4 r = {
pM.m11 * pV.x + pM.m12 * pV.y + pM.m13 * pV.z + pM.m14 * pV.w,
pM.m21 * pV.x + pM.m22 * pV.y + pM.m23 * pV.z + pM.m24 * pV.w,
pM.m31 * pV.x + pM.m32 * pV.y + pM.m33 * pV.z + pM.m34 * pV.w,
pM.m41 * pV.x + pM.m42 * pV.y + pM.m43 * pV.z + pM.m44 * pV.w
};
return r;
}
Я понятия не имею, если это ошибка в SceneKit, или если возможно запрещено применять преобразования к корневому узлу... В любом случае: проблема решена:-)