objective-c – OS X上的SceneKit,包含数千个对象

objective-c – OS X上的SceneKit,包含数千个对象,第1张

概述我正在学习本教程: 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++) 我正在学习本教程: 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 …

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

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

- (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,pIndex*3+1);                elementBuffer[primitiveFillindex+2] = offset + _getIndex(inputPrimitive,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,包含数千个对象全部内容,希望文章能够帮你解决objective-c – OS X上的SceneKit,包含数千个对象所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1022930.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-23
下一篇2022-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存