1

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.

Community
  • 1
  • 1
Ling He
  • 157
  • 9

1 Answers1

5

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.

Community
  • 1
  • 1
Ef Dot
  • 768
  • 6
  • 18
  • 3
    As mentioned in http://stackoverflow.com/questions/41037428/scenekit-scngeometryelement-trianglestrip-vs-triangles, you can skip the `NSData` conversion and use `SCNGeometryElement(indices:primitiveType:)` to generate your index buffer. – Hal Mueller Dec 12 '16 at 19:10
  • This is exactly what I am looking for! Thank you! – Ling He Dec 13 '16 at 09:13
  • Just for someone else need to solve similar problems, drawing too many lines (like 300) in one geometry will crash your app. I do not know the reason, but it happens. – Ling He Dec 13 '16 at 09:14