gpt4 book ai didi

objective-c - OS X 上的 SceneKit 有数千个对象

转载 作者:太空狗 更新时间:2023-10-30 03:32:00 24 4
gpt4 key购买 nike

我正在学习本教程:http://blog.bignerdranch.com/754-scenekit-in-mountain-lion/

我对使用 Scene Kit 很感兴趣,但我的场景可能有数千个球体。为了对 Scene Kit 进行压力测试,我尝试了这个:

SCNSphere *sphere = [SCNSphere sphereWithRadius:0.5];
for (int i=0; i<10; i++) {
for(int j=0; j<10; j++){
for(int k=0; k<10; k++){
SCNNode *myNode = [SCNNode nodeWithGeometry:sphere];
myNode.position = SCNVector3Make(i,j,k);
[root addChildNode:myNode];
}
}
}

例如,这对于 1000 个球体 (10^3)​​ 工作正常,但对于 1,000,000 个球体 (100^3) 会失败(也许不足为奇)。我不介意不能使用一百万个球体,但我想弄清楚合理的上限是多少(5,000?15,000?)以及如何增加它。

我可以做些什么来缓解这种情况?例如我已经尝试过 sphere.segmentCount = 3,虽然这可以加快渲染速度,但它对内存使用没有太大影响,我怀疑这是限制因素。

此外,似乎没有 SCNPoint 类。当球体数量太多时,我正在考虑切换到只显示一个点,但我无法从 SceneKit 文档中看到如何显示一个简单的点——我能看到的最简单的是一个三角形。

非常感谢任何帮助。

编辑:@toyos 建议将 SCNSphere 对象合并到单个 SCNGeometry 对象中(前提是它们不需要独立动画,而它们不需要),但我找不到一个简单的方法来做到这一点。

SCNGeometry 是使用 [SCNGeometry geometryWithSources:(* NSArray)sources geometryWithElements:(* NSArray) elements] 创建的,如记录 here ,但我不清楚如何从我的球体创建一个 SCNGeometry 对象。

例如对于单个球体,我可以看到使用 sphere.geometryElementCount 来获取元素的数量,然后使用它来填充使用 [sphere geometryElementAtIndex:(NSInteger)elementIndex] 的数组这会给我元素,但我不确定如何获得“来源”(或者它们甚至是什么)。获取几何源的方法是[sphere geometrySourcesForSemantic:(NSString*) semantic],但是这个语义字符串是什么? (它的意思是“法线”或“顶点”还是其他东西?文档很有帮助地说语义是“几何源的语义值”。没有说明语义的可能值是什么)

这只是针对单个球体,这毫无意义(因为无论如何 SCNSphere 只是 SCNGeometry 的子类),所以现在我必须添加多个球体。那么,在将球体的顶点添加到我的 SCNGeometry 对象时,我是否必须手动平移球体的顶点?

我只是想找出最明智的方法。

最佳答案

语义字符串是 SCNGeometrySourceSemanticVertex|Normal|Texcoord ...

对于多个球体,答案是肯定的,您必须在展平之前使用当前节点变换来变换顶点/法线。

下面是一个简化的例子(即它只支持合并“input”的 child ,如果它们都具有相同的几何形状)

- (SCNNode *) flattenNodeHierarchy:(SCNNode *) input
{
SCNNode *result = [SCNNode node];

NSUInteger nodeCount = [[input childNodes] count];
if(nodeCount > 0){
SCNNode *node = [[input childNodes] objectAtIndex:0];

NSArray *vertexArray = [node.geometry geometrySourcesForSemantic:SCNGeometrySourceSemanticVertex];
SCNGeometrySource *vertex = [vertexArray objectAtIndex:0];

SCNGeometryElement *element = [node.geometry geometryElementAtIndex:0]; //todo: support multiple elements
NSUInteger primitiveCount = element.primitiveCount;
NSUInteger newPrimitiveCount = primitiveCount * nodeCount;
size_t elementBufferLength = newPrimitiveCount * 3 * sizeof(int); //nTriangle x 3 vertex * size of int
int* elementBuffer = (int*)malloc(elementBufferLength);

/* simple case: here we consider that all the objects to flatten are the same
In the regular case we should iterate on every geometry and accumulate the number of vertex/triangles etc...*/

NSUInteger vertexCount = [vertex vectorCount];
NSUInteger newVertexCount = vertexCount * nodeCount;

SCNVector3 *newVertex = malloc(sizeof(SCNVector3) * newVertexCount);
SCNVector3 *newNormal = malloc(sizeof(SCNVector3) * newVertexCount); //assume same number of normal/vertex

//fill
NSUInteger vertexFillIndex = 0;
NSUInteger primitiveFillIndex = 0;
for(NSUInteger index=0; index< nodeCount; index++){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

node = [[input childNodes] objectAtIndex:index];

NSArray *vertexArray = [node.geometry geometrySourcesForSemantic:SCNGeometrySourceSemanticVertex];
NSArray *normalArray = [node.geometry geometrySourcesForSemantic:SCNGeometrySourceSemanticNormal];
SCNGeometrySource *vertex = [vertexArray objectAtIndex:0];
SCNGeometrySource *normals = [normalArray objectAtIndex:0];

if([vertex bytesPerComponent] != sizeof(float)){
NSLog(@"todo: support other byte per component");
continue;
}

float *vertexBuffer = (float *)[[vertex data] bytes];
float *normalBuffer = (float *)[[normals data] bytes];

CATransform3D t = [node transform];
GLKMatrix4 matrix = MyGLKMatrix4FromCATransform3D(t);

//append source
for(NSUInteger vIndex = 0; vIndex < vertexCount; vIndex++, vertexFillIndex++){
GLKVector3 v = GLKVector3Make(vertexBuffer[vIndex * 3], vertexBuffer[vIndex * 3+1], vertexBuffer[vIndex * 3 + 2]);
GLKVector3 n = GLKVector3Make(normalBuffer[vIndex * 3], normalBuffer[vIndex * 3+1], normalBuffer[vIndex * 3 + 2]);

//transform
v = GLKMatrix4MultiplyVector3WithTranslation(matrix, v);
n = GLKMatrix4MultiplyVector3(matrix, n);

newVertex[vertexFillIndex] = SCNVector3Make(v.x, v.y, v.z);
newNormal[vertexFillIndex] = SCNVector3Make(n.x, n.y, n.z);
}

//append elements
//here we assume that all elements are SCNGeometryPrimitiveTypeTriangles
SCNGeometryElement *element = [node.geometry geometryElementAtIndex:0];
const void *inputPrimitive = [element.data bytes];
size_t bpi = element.bytesPerIndex;

NSUInteger offset = index * vertexCount;

for(NSUInteger pIndex = 0; pIndex < primitiveCount; pIndex++, primitiveFillIndex+=3){
elementBuffer[primitiveFillIndex] = offset + _getIndex(inputPrimitive, bpi, pIndex*3);
elementBuffer[primitiveFillIndex+1] = offset + _getIndex(inputPrimitive, bpi, pIndex*3+1);
elementBuffer[primitiveFillIndex+2] = offset + _getIndex(inputPrimitive, bpi, pIndex*3+2);
}

[pool drain];
}

NSArray *sources = @[[SCNGeometrySource geometrySourceWithVertices:newVertex count:newVertexCount],
[SCNGeometrySource geometrySourceWithNormals:newNormal count:newVertexCount]];

NSData *newElementData = [NSMutableData dataWithBytesNoCopy:elementBuffer length:elementBufferLength freeWhenDone:YES];
NSArray *elements = @[[SCNGeometryElement geometryElementWithData:newElementData
primitiveType:SCNGeometryPrimitiveTypeTriangles
primitiveCount:newPrimitiveCount bytesPerIndex:sizeof(int)]];

result.geometry = [SCNGeometry geometryWithSources:sources elements:elements];

//cleanup
free(newVertex);
free(newNormal);
}

return result;
}

//helpers:
GLKMatrix4 MyGLKMatrix4FromCATransform3D(CATransform3D transform) {
GLKMatrix4 m = {{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}};
return m;
}



GLKVector3 MySCNVector3ToGLKVector3(SCNVector3 vector) {
GLKVector3 v = {{vector.x, vector.y, vector.z}};
return v;
}

关于objective-c - OS X 上的 SceneKit 有数千个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14718407/

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