gpt4 book ai didi

ios - 从 Orientation 获取 SCNNode 的 "up"侧

转载 作者:可可西里 更新时间:2023-11-01 05:12:29 26 4
gpt4 key购买 nike

我在 SCNScene 中有一个 SCNBox。一旦场景为 SCNBox 设置动画,方向就会发生变化,可以通过检查其 presentationNode.orientation 来查看。该值在 SCNVector4 中返回。如何根据 SCNVector4 返回的值确定 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 的回答,我想出了以下代码,但它不起作用。希望这将有助于接近最终目标。我还使用了在 Extracting vertices from 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<vectorCount; i++) {

// Assuming that bytes per component is 4 (a float)
// If it was 8 then it would be a double (aka CGFloat)
float vectorData[componentsPerVector];

// The range of bytes for this vector
NSRange byteRange = NSMakeRange(i*stride + offset, // Start at current stride + offset
bytesPerVector); // and read the lenght of one vector

// Read into the vector data buffer
[vertexSource.data getBytes:&vectorData range:byteRange];

// At this point you can read the data from the float array
float x = vectorData[0];
float y = vectorData[1];
float z = vectorData[2];

// ... Maybe even save it as an SCNVector3 for later use ...
vertices[i] = SCNVector3Make(x, y, z);

// ... or just log it
NSLog(@"x:%f, y:%f, z:%f", x, y, z);
float product = (x * finalVector.x) + (y * finalVector.y) + (z * finalVector.z);
if (product > 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;
}

关于ios - 从 Orientation 获取 SCNNode 的 "up"侧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24110918/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com