Reputation:
I am aware that SceneKit
allows you to create certain basic shapes like box, sphere etc. I was wondering if you can create complex geometries using scene kit. I found this tutorial here and it was helpful. I exported some geometry BIMServer in json
format. I want to take that and use it in SceneKit but I am having difficulties. Is it possible to do this in SceneKit? Below is a sample of some of the geometries i extracted.
{
"id" : "2O2Fr$t4X7Zf8NOew3FNtn",
"type" : "IFCWALLSTANDARDCASE",
"geometry" : {
"metadata" : { "formatVersion" : 3 },
"materials": [],
"vertices": [ 8.8,0.2085,0.0, 3.4479692,0.2085,0.0, 3.4479692,0.2085,2.42, 2.6349692,0.2085,2.42, 2.6349692,0.2085,0.0, 0.0,0.2085,0.0, 0.0,0.2085,3.1, 8.8,0.2085,3.1, 8.383,0.2085,2.52, 8.383,0.2085,0.1, 3.548,0.2085,2.52, 3.548,0.2085,0.1, 8.8,0.2085,0.0, 3.4479692,0.2085,0.0, 3.4479692,-0.2085,0.0, 8.8,-0.2085,0.0, 3.4479692,-0.2085,2.42, 3.4479692,0.2085,2.42, 3.4479692,-0.2085,0.0, 3.4479692,0.2085,0.0, 2.6349692,-0.2085,2.42, 2.6349692,0.2085,2.42, 3.4479692,-0.2085,2.42, 3.4479692,0.2085,2.42, 2.6349692,-0.2085,0.0, 2.6349692,0.2085,0.0, 2.6349692,-0.2085,2.42, 2.6349692,0.2085,2.42, 2.6349692,0.2085,0.0, 0.0,0.2085,0.0, 0.0,-0.2085,0.0, 2.6349692,-0.2085,0.0, 0.0,0.2085,0.0, 0.0,0.2085,3.1, 0.0,-0.2085,0.0, 0.0,-0.2085,3.1, 8.8,0.2085,3.1, 0.0,0.2085,3.1, 0.0,-0.2085,3.1, 8.8,-0.2085,3.1, 8.8,-0.2085,0.0, 8.8,-0.2085,3.1, 8.8,0.2085,0.0, 8.8,0.2085,3.1, 8.383,-0.2085,2.52, 8.383,0.2085,2.52, 8.383,-0.2085,0.1, 8.383,0.2085,0.1, 3.548,-0.2085,2.52, 3.548,0.2085,2.52, 8.383,-0.2085,2.52, 8.383,0.2085,2.52, 8.383,-0.2085,0.1, 8.383,0.2085,0.1, 3.548,-0.2085,0.1, 3.548,0.2085,0.1, 3.548,-0.2085,0.1, 3.548,0.2085,0.1, 3.548,-0.2085,2.52, 3.548,0.2085,2.52, 0.0,-0.2085,0.0, 2.6349692,-0.2085,0.0, 2.6349692,-0.2085,2.42, 3.4479692,-0.2085,2.42, 3.4479692,-0.2085,0.0, 8.8,-0.2085,0.0, 8.8,-0.2085,3.1, 0.0,-0.2085,3.1, 8.383,-0.2085,0.1, 3.548,-0.2085,0.1, 8.383,-0.2085,2.52, 3.548,-0.2085,2.52 ],
"normals": [ 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0 ],
"colors": [ ],
"uvs": [ ],
"faces": [ 32, 8,7,0,8,7,0, 32, 8,0,9,8,0,9, 32, 7,8,10,7,8,10, 32, 10,2,3,10,2,3, 32, 2,10,11,2,10,11, 32, 11,9,1,11,9,1, 32, 7,10,6,7,10,6, 32, 10,3,6,10,3,6, 32, 3,4,5,3,4,5, 32, 6,3,5,6,3,5, 32, 9,0,1,9,0,1, 32, 11,1,2,11,1,2, 32, 14,12,15,14,12,15, 32, 13,12,14,13,12,14, 32, 18,16,17,18,16,17, 32, 18,17,19,18,17,19, 32, 22,20,21,22,20,21, 32, 22,21,23,22,21,23, 32, 26,24,25,26,24,25, 32, 26,25,27,26,25,27, 32, 29,31,30,29,31,30, 32, 29,28,31,29,28,31, 32, 33,32,34,33,32,34, 32, 35,33,34,35,33,34, 32, 38,39,37,38,39,37, 32, 39,36,37,39,36,37, 32, 41,40,42,41,40,42, 32, 43,41,42,43,41,42, 32, 46,44,45,46,44,45, 32, 46,45,47,46,45,47, 32, 50,48,49,50,48,49, 32, 50,49,51,50,49,51, 32, 55,52,53,55,52,53, 32, 54,52,55,54,52,55, 32, 58,56,57,58,56,57, 32, 58,57,59,58,57,59, 32, 67,60,62,67,60,62, 32, 62,63,71,62,63,71, 32, 67,62,71,67,62,71, 32, 62,60,61,62,60,61, 32, 71,63,69,71,63,69, 32, 67,71,66,67,71,66, 32, 66,71,70,66,71,70, 32, 69,64,68,69,64,68, 32, 70,68,65,70,68,65, 32, 66,70,65,66,70,65, 32, 69,63,64,69,63,64, 32, 68,64,65,68,64,65 ]
}
} ,{
"id" : "2O2Fr$t4X7Zf8NOew3FKGS",
"type" : "IFCWALLSTANDARDCASE",
"geometry" : {
"metadata" : { "formatVersion" : 3 },
"materials": [],
"vertices": [ 3.583,0.062,0.0, 3.583,0.062,2.795, 6.661338E-16,0.062,0.0, 6.661338E-16,0.062,2.795, 6.661338E-16,0.062,0.0, 6.661338E-16,0.062,2.795, 6.661338E-16,-0.062,0.0, 6.661338E-16,-0.062,2.795, 6.661338E-16,-0.062,0.0, 6.661338E-16,-0.062,2.795, 3.583,-0.062,0.0, 3.583,-0.062,2.795, 3.583,-0.062,0.0, 3.583,-0.062,2.795, 3.583,0.062,0.0, 3.583,0.062,2.795, 3.583,0.062,0.0, 6.661338E-16,0.062,0.0, 6.661338E-16,-0.062,0.0, 3.583,-0.062,0.0, 3.583,0.062,2.795, 6.661338E-16,0.062,2.795, 6.661338E-16,-0.062,2.795, 3.583,-0.062,2.795 ],
"normals": [ 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0 ],
"colors": [ ],
"uvs": [ ],
"faces": [ 32, 1,0,2,1,0,2, 32, 3,1,2,3,1,2, 32, 5,4,6,5,4,6, 32, 7,5,6,7,5,6, 32, 9,8,10,9,8,10, 32, 11,9,10,11,9,10, 32, 13,12,14,13,12,14, 32, 15,13,14,15,13,14, 32, 17,19,18,17,19,18, 32, 17,16,19,17,16,19, 32, 22,23,21,22,23,21, 32, 23,20,21,23,20,21 ]
}
Upvotes: 1
Views: 1354
Reputation: 2221
I know is a bit too late, but if someone else like me find this will be cool to have a better answer, for those who want to understand how SceneKit custom geometry works, I see some issues with the geometry but really don't know how must looks like, this code is far from perfect but is a start point.
class JSONGeometry: Decodable {
class Geometry: Decodable {
var vertices: [CGFloat]
var normals: [CGFloat]
var faces: [Int16]
init(vertices: [CGFloat], normals: [CGFloat], faces: [Int16]) {
self.vertices = vertices
self.normals = normals
self.faces = faces
}
}
static let data: [JSONGeometry] = {
let json = """
[{
"id" : "2O2Fr$t4X7Zf8NOew3FNtn",
"type" : "IFCWALLSTANDARDCASE",
"geometry" : {
"metadata" : { "formatVersion" : 3 },
"materials": [],
"vertices": [ 8.8,0.2085,0.0, 3.4479692,0.2085,0.0, 3.4479692,0.2085,2.42, 2.6349692,0.2085,2.42, 2.6349692,0.2085,0.0, 0.0,0.2085,0.0, 0.0,0.2085,3.1, 8.8,0.2085,3.1, 8.383,0.2085,2.52, 8.383,0.2085,0.1, 3.548,0.2085,2.52, 3.548,0.2085,0.1, 8.8,0.2085,0.0, 3.4479692,0.2085,0.0, 3.4479692,-0.2085,0.0, 8.8,-0.2085,0.0, 3.4479692,-0.2085,2.42, 3.4479692,0.2085,2.42, 3.4479692,-0.2085,0.0, 3.4479692,0.2085,0.0, 2.6349692,-0.2085,2.42, 2.6349692,0.2085,2.42, 3.4479692,-0.2085,2.42, 3.4479692,0.2085,2.42, 2.6349692,-0.2085,0.0, 2.6349692,0.2085,0.0, 2.6349692,-0.2085,2.42, 2.6349692,0.2085,2.42, 2.6349692,0.2085,0.0, 0.0,0.2085,0.0, 0.0,-0.2085,0.0, 2.6349692,-0.2085,0.0, 0.0,0.2085,0.0, 0.0,0.2085,3.1, 0.0,-0.2085,0.0, 0.0,-0.2085,3.1, 8.8,0.2085,3.1, 0.0,0.2085,3.1, 0.0,-0.2085,3.1, 8.8,-0.2085,3.1, 8.8,-0.2085,0.0, 8.8,-0.2085,3.1, 8.8,0.2085,0.0, 8.8,0.2085,3.1, 8.383,-0.2085,2.52, 8.383,0.2085,2.52, 8.383,-0.2085,0.1, 8.383,0.2085,0.1, 3.548,-0.2085,2.52, 3.548,0.2085,2.52, 8.383,-0.2085,2.52, 8.383,0.2085,2.52, 8.383,-0.2085,0.1, 8.383,0.2085,0.1, 3.548,-0.2085,0.1, 3.548,0.2085,0.1, 3.548,-0.2085,0.1, 3.548,0.2085,0.1, 3.548,-0.2085,2.52, 3.548,0.2085,2.52, 0.0,-0.2085,0.0, 2.6349692,-0.2085,0.0, 2.6349692,-0.2085,2.42, 3.4479692,-0.2085,2.42, 3.4479692,-0.2085,0.0, 8.8,-0.2085,0.0, 8.8,-0.2085,3.1, 0.0,-0.2085,3.1, 8.383,-0.2085,0.1, 3.548,-0.2085,0.1, 8.383,-0.2085,2.52, 3.548,-0.2085,2.52 ],
"normals": [ 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0 ],
"colors": [ ],
"uvs": [ ],
"faces": [ 32, 8,7,0,8,7,0, 32, 8,0,9,8,0,9, 32, 7,8,10,7,8,10, 32, 10,2,3,10,2,3, 32, 2,10,11,2,10,11, 32, 11,9,1,11,9,1, 32, 7,10,6,7,10,6, 32, 10,3,6,10,3,6, 32, 3,4,5,3,4,5, 32, 6,3,5,6,3,5, 32, 9,0,1,9,0,1, 32, 11,1,2,11,1,2, 32, 14,12,15,14,12,15, 32, 13,12,14,13,12,14, 32, 18,16,17,18,16,17, 32, 18,17,19,18,17,19, 32, 22,20,21,22,20,21, 32, 22,21,23,22,21,23, 32, 26,24,25,26,24,25, 32, 26,25,27,26,25,27, 32, 29,31,30,29,31,30, 32, 29,28,31,29,28,31, 32, 33,32,34,33,32,34, 32, 35,33,34,35,33,34, 32, 38,39,37,38,39,37, 32, 39,36,37,39,36,37, 32, 41,40,42,41,40,42, 32, 43,41,42,43,41,42, 32, 46,44,45,46,44,45, 32, 46,45,47,46,45,47, 32, 50,48,49,50,48,49, 32, 50,49,51,50,49,51, 32, 55,52,53,55,52,53, 32, 54,52,55,54,52,55, 32, 58,56,57,58,56,57, 32, 58,57,59,58,57,59, 32, 67,60,62,67,60,62, 32, 62,63,71,62,63,71, 32, 67,62,71,67,62,71, 32, 62,60,61,62,60,61, 32, 71,63,69,71,63,69, 32, 67,71,66,67,71,66, 32, 66,71,70,66,71,70, 32, 69,64,68,69,64,68, 32, 70,68,65,70,68,65, 32, 66,70,65,66,70,65, 32, 69,63,64,69,63,64, 32, 68,64,65,68,64,65 ]
}
} ,{
"id" : "2O2Fr$t4X7Zf8NOew3FKGS",
"type" : "IFCWALLSTANDARDCASE",
"geometry" : {
"metadata" : { "formatVersion" : 3 },
"materials": [],
"vertices": [ 3.583,0.062,0.0, 3.583,0.062,2.795, 6.661338E-16,0.062,0.0, 6.661338E-16,0.062,2.795, 6.661338E-16,0.062,0.0, 6.661338E-16,0.062,2.795, 6.661338E-16,-0.062,0.0, 6.661338E-16,-0.062,2.795, 6.661338E-16,-0.062,0.0, 6.661338E-16,-0.062,2.795, 3.583,-0.062,0.0, 3.583,-0.062,2.795, 3.583,-0.062,0.0, 3.583,-0.062,2.795, 3.583,0.062,0.0, 3.583,0.062,2.795, 3.583,0.062,0.0, 6.661338E-16,0.062,0.0, 6.661338E-16,-0.062,0.0, 3.583,-0.062,0.0, 3.583,0.062,2.795, 6.661338E-16,0.062,2.795, 6.661338E-16,-0.062,2.795, 3.583,-0.062,2.795 ],
"normals": [ 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, -1.0,-0.0,-0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0 ],
"colors": [ ],
"uvs": [ ],
"faces": [ 32, 1,0,2,1,0,2, 32, 3,1,2,3,1,2, 32, 5,4,6,5,4,6, 32, 7,5,6,7,5,6, 32, 9,8,10,9,8,10, 32, 11,9,10,11,9,10, 32, 13,12,14,13,12,14, 32, 15,13,14,15,13,14, 32, 17,19,18,17,19,18, 32, 17,16,19,17,16,19, 32, 22,23,21,22,23,21, 32, 23,20,21,23,20,21 ]
}
}]
"""
guard let data = json.data(using: .utf8) else { return [] }
guard let result = try? JSONDecoder().decode([JSONGeometry].self, from: data) else { return [] }
return result
}()
var id: String
var type: String
var geometry: Geometry
var toSCN: SCNGeometry {
var sources: [SCNGeometrySource] = []
let vertices = SCNGeometrySource(
vertices: geometry.vertices.eachSlice(3).map{ SCNVector3($0[0], $0[1], $0[2]) }
)
sources.append(vertices)
if geometry.normals.count > 0 {
let normals = SCNGeometrySource(
normals: geometry.normals.eachSlice(3).map{ SCNVector3($0[0], $0[1], $0[2]) }
)
sources.append(normals)
}
let indices = Data(
bytes: geometry.faces.map{ Int16($0) },
count: MemoryLayout<Int16>.size * geometry.faces.count
)
let elements = [
SCNGeometryElement(
data: indices,
primitiveType: .triangles,
primitiveCount: geometry.faces.count / 3,
bytesPerIndex: MemoryLayout<Int16>.size
)
]
return SCNGeometry(sources: sources, elements: elements)
}
init(id: String, type: String, geometry: Geometry) {
self.id = id
self.type = type
self.geometry = geometry
}
}
extension Sequence {
func eachSlice(_ clump:Int) -> [[Self.Element]] {
return self.reduce(into:[]) { memo, cur in
if memo.count == 0 {
return memo.append([cur])
}
if memo.last!.count < clump {
memo.append(memo.removeLast() + [cur])
} else {
memo.append([cur])
}
}
}
}
I've a gist where I will update a code similar to this, because theres some thinks that I don't understand quite well right now like UV Mapping and normals (don't really now whats for).
Regards
Upvotes: 2
Reputation: 1196
Ouch! SceneKit is great but, besides the few primitives it offers, it is not a modeler. It's far easier and better in every way to create models in an app dedicated to 3-D modeling. A lot of folks on the forum use Blender, free and redily available. I use Cinema 4D, many other options are available. The only necessity is that they output DAE (Collada) files.
The learning curve in using such an app is nothing compared to the frustration you will most likely experience using such low-level construction techniques.
Once you import a DAE file into Xcode it can be inspected in the editor window. You can move nodes, rearrange then, rename them and delete them. More on that: Transform and Rotate in Scenekit
Upvotes: 0