从Orientation获取SCNNode的“up”方面

我在SCNBox中有一个SCNBox。 一旦场景动画化, SCNBox变化就是方向,可以通过检查其presentationNode.orientation来看到。 此值在SCNVector4中返回。 如何根据SCNBox中返回的值确定SCNBox哪一侧是朝上的一侧?

我试图规范化数据并提出以下数据

 Side 1 = (-x, 0, 0, +x) Side 2 = (0, -x, 0 +y) Side 3 = (-x, +x, -y, y) Side 4 = (x, x, y, y) Side 5 = (-x, 0, +y, 0) Side 6 = (-x, -y, +y, -x) 

不幸的是,这并不总是正确的,对它进行检查有时会偶尔返回无效的边。

是否有可靠的方法从几何的方向属性确定SCNBox朝上一侧?

编辑:根据Toyos的回答,我提出了以下代码,但这不起作用。 希望这有助于更接近最终目标。 我还使用了从scenekit中提取顶点的代码来获取我的SCNBoxNode的顶点。

 - (NSNumber *)valueForRotation:(SCNVector4)rotation andGeometry:(SCNGeometry*)geometry { SCNVector4 inverse = SCNVector4Make(rotation.x, rotation.y, rotation.z, -rotation.w); CATransform3D transform = CATransform3DMakeRotation(inverse.w, inverse.x, inverse.y, inverse.z); GLKMatrix4 matrix = GLKMatrix4Make(transform.m11, transform.m12, transform.m13, transform.m14, transform.m21, transform.m22, transform.m23, transform.m24, transform.m31, transform.m32, transform.m33, transform.m34, transform.m41, transform.m42, transform.m43, transform.m44); GLKVector4 vector = GLKVector4Make(rotation.x, rotation.y, rotation.z, rotation.w); GLKVector4 finalVector = GLKMatrix4MultiplyVector4(matrix, vector); NSArray *vertexSources = [geometry geometrySourcesForSemantic:SCNGeometrySourceSemanticVertex]; SCNGeometrySource *vertexSource = vertexSources[0]; // TODO: Parse all the sources NSInteger stride = vertexSource.dataStride; // in bytes NSInteger offset = vertexSource.dataOffset; // in bytes NSInteger componentsPerVector = vertexSource.componentsPerVector; NSInteger bytesPerVector = componentsPerVector * vertexSource.bytesPerComponent; NSInteger vectorCount = vertexSource.vectorCount; SCNVector3 vertices[vectorCount]; // A new array for vertices // for each vector, read the bytes NSLog(@"vetor count %i",vectorCount); float highestProduct = 0; int highestVector = -1; NSMutableArray *highVectors; for (NSInteger i=0; i highestProduct) { highestProduct = product; highestVector = i; } } NSLog(@"highestProduct = %f",highestProduct); NSLog(@"highestVector = %i",highestVector); NSLog(@"top verticy = %f, %f, %f",vertices[highestVector].x,vertices[highestVector].y,vertices[highestVector].z); return [NSNumber numberWithInt:highestVector]; } 

这是一个返回面朝上的面的索引的方法。 它假定“boxNode”是由6个面组成的框,具有以下(任意)顺序:前/右/后/左/上/下。 它返回面朝上的面部索引。 别忘了导入。 对于任意网格,你必须使用面法线而不是“boxNormals”(这是不明显的计算,因为SceneKit网格每个顶点有一个法线,而不是每个面一个法线,所以你必须计算每个面的法线你自己)。

 - (NSUInteger) boxUpIndex:(SCNNode *)boxNode { SCNVector4 rotation = boxNode.rotation; SCNVector4 invRotation = rotation; invRotation.w = -invRotation.w; SCNVector3 up = SCNVector3Make(0,1,0); //rotate up by invRotation SCNMatrix4 transform = SCNMatrix4MakeRotation(invRotation.w, invRotation.x, invRotation.y, invRotation.z); GLKMatrix4 glkTransform = SCNMatrix4ToGLKMatrix4(transform); GLKVector3 glkUp = SCNVector3ToGLKVector3(up); GLKVector3 rotatedUp = GLKMatrix4MultiplyVector3(glkTransform, glkUp); //build box normals (arbitrary order here) GLKVector3 boxNormals[6] = {{{0,0,1}}, {{1,0,0}}, {{0,0,-1}}, {{-1,0,0}}, {{0,1,0}}, {{0,-1,0}}, }; int bestIndex = 0; float maxDot = -1; for(int i=0; i<6; i++){ float dot = GLKVector3DotProduct(boxNormals[i], rotatedUp); if(dot > maxDot){ maxDot = dot; bestIndex = i; } } return bestIndex; } 

node.orientation将为您提供四元数。 您也可以使用node.eulerAngles或node.rotation(轴角度),这样可以简化数学运算。

在所有情况下,我认为您需要将反向旋转应用于向量[0,1,0](向上向量)。 结果向量(V)将为您提供正面方向。 然后找到正面,比较框面和V的点积。最高点积是面朝上的面。

(另一种方法是旋转盒子的面,然后用[0,1,0]做点积。)