8
votes

I'm current working on developing OS X software using Swift to display a point cloud reading from a PLY file. The file is converted to an array of PointCloudVertex which is defined as follows:

struct PointCloudVertex {
    let x: Double, y: Double, z: Double
    let r: Double, g: Double, b: Double
}

Then I try to build a SCNGeometry from the array:

var vertices = [PointCloudVertex]()
for p in points {
    let v = PointCloudVertex(x: p[0], y: p[1], z: p[2], r: p[3], g: p[4], b: p[5])
    vertices.append(v)
}
let vertexData = NSData(bytes: &vertices, length: sizeof(PointCloudVertex) * points.count)
let positionSource = SCNGeometrySource(data: vertexData, semantic: SCNGeometrySourceSemanticVertex, vectorCount: points.count, floatComponents: true, componentsPerVector: 3, bytesPerComponent: sizeof(Double), dataOffset: 0, dataStride: sizeof(PointCloudVertex))
let colorSource = SCNGeometrySource(data: vertexData, semantic: SCNGeometrySourceSemanticColor, vectorCount: points.count, floatComponents: true, componentsPerVector: 3, bytesPerComponent: sizeof(CGFloat), dataOffset: sizeof(Double) * 3, dataStride: sizeof(PointCloudVertex))
let elements = SCNGeometryElement(data: nil, primitiveType: .Point, primitiveCount: points.count, bytesPerIndex: sizeof(Int))
let pointCloud = SCNGeometry(sources: [positionSource, colorSource], elements: [elements])
let pcNode = SCNNode(geometry: pointCloud)
self.modelScene.rootNode.addChildNode(pcNode)

where points is a [[Double]] which stores all the points' position and color data. I try to display the point cloud. The positions are correct but all points are in black rather than in the color I pass to the PointCloudVertex. Moreover, I also tried to use SCNMaterial to associate with the geometry the color is still black. So how can I display the point cloud in a colorful way? I know the SceneKit has some custom rendering API and I wonder whether it will help. It would be helpful if there are some code for this because I'm not so familiar with OpenGL or metal drawing stuff.

By the way, I also tried to use SCNSphere to display the point cloud, it works but I need to create one SCNSphere for every single point. My Mac ran out of memory using this method since I have around 1 million points to display.

The PLY file is in the following format:

ply
format ascii 1.0
comment VCGLIB generated
element vertex 684398
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
property uchar alpha
end_header
7.42808 15.3133 1.45829 55 45 43 255 
3.92053 20.8015 -32.8147 156 141 121 255 
4.80496 21.0725 -34.3995 160 146 133 255 
8.09035 14.6247 33.5683 127 119 101 255 
14.66 20.5331 -26.406 70 64 40 255 
-0.911526 14.6359 7.66687 157 146 150 255 
...

In my PLY file reader method, each row in the body part is converted to a [Double] (the last column, which is alpha value, is discarded). For red, green and blue value, I have divided them by 255 so the value is between 0 and 1.

Could you provide PLY file example?John Tracid
Did you try to use the lightingModel "SCNLightingModelConstant" in your material? (just to remove the impact of the lighting from the equation).Toyos
It works! Thank you @Toyos!Evan Huang