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.