My app generates ply files after scanning objects. After ios 14 update the color of my 3d models does not load correctly. Also I am unable to view ply files in xcode (works fine in preview).
Anyone know the workaround to this problem?
I tired reading ply file content and display vertices and faces in scene geometry but it takes too long to load a file.
Apparently creating mdlAsset() throws some Metal warning and the mesh color does not show up properly.
Here are the sample images from ios 13 and 14 preview in sceneKit.
same problem,i found it is a SceneKit's bug, i had a solution that read .ply file with C, and creat a SCNGeometry instance with data, main code:
bool readFaceAndVertexCount(char* filePath, int *vertexCount, int *faceCount);
example:
bool readFaceAndVertexCount(char* filePath, int *vertexCount, int *faceCount) {
char data[100];
FILE *fp;
if((fp = fopen(filePath,"r")) == NULL)
{
printf("error!");
return false;
}
while (!feof(fp))
{
fgets(data,1024,fp);
unsigned long i = strlen(data);
data[i - 1] = '\0';
if (strstr(data, "element vertex") != NULL) {
char *res = strtok(data," ");
while (res != NULL) {
res = strtok(NULL, " ");
if (res != NULL) {
*vertexCount = atoi(res);
}
}
}
if (strstr(data, "element face") != NULL) {
char *res = strtok(data," ");
while (res != NULL) {
res = strtok(NULL, " ");
if (res != NULL) {
*faceCount = atoi(res);
}
}
}
if (*faceCount > 0 && *vertexCount > 0) {
break;
}
}
fclose(fp);
return true;
}
2, read data to array: in .c
// you need to implement with your files
bool readPlyFile(char* filePath, const int vertexCount, int faceCount, float *vertex, float *color, int *elment)
in .swift:
var vertex: [Float] = Array.init(repeating: 0, count: Int(vertexCount) * 3)
var color: [Float] = Array.init(repeating: 0, count: Int(vertexCount) * 3)
var face: [Int32] = Array.init(repeating: 0, count: Int(faceCount) * 3)
readPlyFile(UnsafeMutablePointer<Int8>(mutating: url.path),vertexCount,faceCount,&vertex,&color,&face)
3 creat a custom SCNGeometry:
let positionData = NSData.init(bytes: vertex, length: MemoryLayout<Float>.size * vertex.count)
let vertexSource = SCNGeometrySource.init(data: positionData as Data, semantic: .vertex, vectorCount: Int(vertexCount), usesFloatComponents: true, componentsPerVector: 3, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<Float>.size * 3)
let colorData = NSData.init(bytes: color, length: MemoryLayout<Float>.size * color.count)
let colorSource = SCNGeometrySource.init(data: colorData as Data, semantic: .color, vectorCount: Int(vertexCount), usesFloatComponents: true, componentsPerVector: 3, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<Float>.size * 3)
let indexData = NSData(bytes: face, length: MemoryLayout<Int32>.size * face.count)
let element = SCNGeometryElement(data: indexData as Data, primitiveType: SCNGeometryPrimitiveType.triangles, primitiveCount: Int(faceCount), bytesPerIndex: MemoryLayout<Int32>.size)
let gemetry = SCNGeometry.init(sources: [vertexSource,colorSource], elements: [element])
let node = SCNNode.init(geometry: gemetry)
let scene = SCNScene.init()
node.geometry?.firstMaterial?.cullMode = .back
node.geometry?.firstMaterial?.isDoubleSided = true
scene.rootNode.addChildNode(node)
scnView.scene = scene
it work! and faster!