Ling He
Ling He

Reputation: 167

How to draw tens of thousands of lines in SceneKit?

I am going to draw a lot of lines in SceneKit. I searched how to draw lines and found this answer

It works well for me, except it is not suitable for drawing a huge number of lines. When I am drawing tens of thousands of lines, the occupied RAM will be horrible (n Gb).

I am wondering if there is a way I can draw a large number of lines efficiently. All I need is 3D lines, whose from-to coordination and length may be different.

Upvotes: 1

Views: 1637

Answers (1)

Ef Dot
Ef Dot

Reputation: 768

The method described in your referenceed answer is correct, you just have not create SCNGeometrySource/SCNGeometryElement/SCNNode for each line, just fill the arrays:

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

And then create geometry source from NSData with stride:

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

If you have 10000 lines, then your positions buffer will be 2*3*10000*8 = 480KB, and indices 2*10000*4 = 80KB, which is really not much for GPU.

You can even further reduce buffers if you can reduce length of indices and/or positions. For example, if all your coordinates is integers in range -127..128 then passing floatComponent:NO, bytesPerComponent:1 would reduce positions buffer to 60KB).

Of course, this is applicible if all of your lines have same material properties. Otherwise, you have to group all lines with same properties in SCNGeometrySource/SCNGeometryElement/SCNNode.

Upvotes: 5

Related Questions