SceneKit如何绘制上万条线?

How to draw tens of thousands of lines in SceneKit?

我要在SceneKit中画很多线条。我搜索了如何画线并找到 this answer

它对我来说很好,除了它不适合画大量的线条。当我在画几万条线时,占用的RAM会很恐怖(n Gb)。

我想知道是否有一种方法可以有效地绘制大量线条。我只需要 3D 线,其前后坐标和长度可能不同。

你的referenceed answer中描述的方法是正确的,你只是没有为每行创建SCNGeometrySource/SCNGeometryElement/SCNNode,只是填充数组:

SCNVector3 positions[] = {
    SCNVector3Make(0.0, 0.0, 0.0),    // line1 begin  [0]
    SCNVector3Make(10.0, 10.0, 10.0), // line1 end    [1]
    SCNVector3Make(5.0, 10.0, 10.0),  // line2 begin  [2]
    SCNVector3Make(10.0, 5.0, 10.0)   // line2 end    [3]
};

int indices[] = {0, 1, 2, 3};
              // ^^^^  ^^^^
              // 1st   2nd
              // line  line

然后从 NSData 创建几何源,步幅为:

NSData *data = [NSData dataWithBytes:positions length:sizeof(positions)];

SCNGeometrySource *vertexSource = [SCNGeometrySource geometrySourceWithData:data
                                            semantic:SCNGeometrySourceSemanticVertex
                                         vectorCount:POSITION_COUNT
                                     floatComponents:YES
                                 componentsPerVector:3 // x, y, z
                                   bytesPerComponent:sizeof(CGFloat) // size of x/y/z/ component of SCNVector3
                                          dataOffset:0 
                                          dataStride:sizeof(SCNVector3)*2]; // offset in buffer to the next line positions

如果您有 10000 行,那么您的头寸缓冲区将为 2*3*10000*8 = 480KB,索引为 2*10000*4 = 80KB,对于GPU来说确实不多。

如果可以减少索引 and/or 位置的长度,您甚至可以进一步减少缓冲区。例如,如果您所有的坐标都是 -127..128 范围内的整数,那么传递 floatComponent:NO, bytesPerComponent:1 会将位置缓冲区减少到 60KB).

当然,如果您的所有行都具有相同的 material 属性,则这适用。否则,您必须将所有具有相同属性的行分组到 SCNGeometrySource/SCNGeometryElement/SCNNode.